Re: [Haskell-beginners] Dipping Toes Into Haskell

So I've finally had a chance to revisit my tictactoe game.
import Control.Lens
data Piece = X | O | E deriving Show
type Row = [Piece]
type Board = [Row]
*data Position = Int Int deriving Show*
-- put an X or O in a position
*move :: Board -> Piece -> Position -> Board*
move board piece position = board
main :: IO ()
main = putStrLn "Hello World"
-- using Lenses
-- https://github.com/ekmett/lens/wiki/Examples
-- http://lens.github.io/tutorial.html
--
http://blog.jakubarnold.cz/2014/07/14/lens-tutorial-introduction-part-1.html
--let r1 = (E,E,E)
--let r2 = (E,E,E)
--let r3 = (E,E,E)
--let board = (r1,r2,r3)
Now, if I want to make a move, I'll want to set a *piece* on a *position*,
on a *board*. Let's assume the board has the following shape.
λ> let r1 = (E,E,E)
λ> let r2 = (E,E,E)
λ> let r3 = (E,E,E)
λ> let board = (r1,r2,r3)
((E,E,E),(E,E,E),(E,E,E))
To return an updated board, I dug around and *i)* couldn't find a core
Haskell equivalent to Clojure's update-in
http://clojuredocs.org/clojure.core/update-in. *ii)* Zippers only deal
with trees of left / right nodes. *iii)* So that left me with Control.Lens
https://github.com/ekmett/lens/wiki/Examples. Now I can easily inspect
and update the board like so.
λ> board^*._**2._1*
E
λ> set (*_2._1*) 42 board
((E,E,E),(42,E,E),(E,E,E))
I can then parameterize _2 or _1 like so.
λ> let a = _2
λ> board ^. a
(E,E,E)
But I can't figure out how to include that parameter's type into a
*Position* type definition. I've tried these unsuccessfully.
*data Position = Int Int deriving Show -- original type definition*
*data Position = Simple Lens (Int a) (Int a) deriving Show -- failing try
1*
move :: Board -> Piece -> Position -> Board
move board piece position = set (position) piece board -- want to use this
instead of "set (*_2._1*) 42 board"
Any ideas?
:)
Tim Washington
Interruptsoftware.com http://interruptsoftware.com
On Thu, Mar 12, 2015 at 5:18 PM, Timothy Washington
Veeery nice. Thanks for your insights.
The Typeclass stuff making a lot more sense now. And hence ghc-mod's (Interactive-Haskell's) behaviour makes more sense to me. It's working like a charm.
I'll play around with nested list manipulation this evening.
Cheers
Tim Washington Interruptsoftware.com http://interruptsoftware.com
On Thu, Mar 12, 2015 at 8:03 PM, Mike Meyer
wrote: On Thu, Mar 12, 2015 at 6:02 PM, Timothy Washington
wrote: To get started, I'm trying to implement a simple *tictactoe* game. And I would like to be able to represent a Piece on the board, as either the string "X" or "O". This is what I have so far.
module Main where
data Piece = X | O type Row = [Piece] type Board = [Row]
-- put an X or O in a position move :: Board -> Piece -> Board move board piece = board
-- check win vertically -- check win horizontally -- check win diagonally
main :: IO () main = putStrLn "Hello World"
*A)* Now, I'd like to be able to *load code interactively*, preferably within emacs. However I don't have access to my types with *ghci* or *ghc-mod (Interactive-Haskell)*. In either case, this call fails with the below error.
let p = Piece X <interactive>:20:9-13: Not in scope: data constructor `Piece'
Piece is the data TYPE. It has two constructors, X, and O. If you load your module into ghci, you can do ":t X" to get the type of X, which is Piece. You want to do "let p = X" here.
Check your mode docs while editing the haskell file. There should be a command to load the current buffer into a ghci running in an interactive emacs buffer.
*B)* And how do I make a *custom datatype* that's one of two strings (enumeration of either "X" or "O"). Cabal builds and runs the abouve code, so I know it can compile. But I'm confused as to where X or O is defined, and how I would supply it as an input.
As noted, you can derive "Show" so that Piece types print as "X" and "O". Similarly, you can derive "Read":
data Piece = X | O deriving (Show, Read)
so that you can then read "X" and get back an X when the context calls for a Piece value:
*Main> read "X" :: Piece
X
However, this isn't used a lot, as it tends to be slow and not very flexible for more complex types. For instance, it will let you read in lists of Pieces and lists of lists, but you'l lhave to use the list syntax, not something that looks like an actual board when printed.

Hi Tim, Staying from clojure? :-)
On Mar 22, 2015, at 12:33 PM, Timothy Washington
wrote: So I've finally had a chance to revisit my tictactoe game.
import Control.Lens
data Piece = X | O | E deriving Show type Row = [Piece] type Board = [Row] data Position = Int Int deriving Show
-- put an X or O in a position move :: Board -> Piece -> Position -> Board move board piece position = board
main :: IO () main = putStrLn "Hello World"
-- using Lenses -- https://github.com/ekmett/lens/wiki/Examples https://github.com/ekmett/lens/wiki/Examples -- http://lens.github.io/tutorial.html http://lens.github.io/tutorial.html -- http://blog.jakubarnold.cz/2014/07/14/lens-tutorial-introduction-part-1.html http://blog.jakubarnold.cz/2014/07/14/lens-tutorial-introduction-part-1.html
--let r1 = (E,E,E) --let r2 = (E,E,E) --let r3 = (E,E,E) --let board = (r1,r2,r3)
Now, if I want to make a move, I'll want to set a piece on a position, on a board. Let's assume the board has the following shape.
λ> let r1 = (E,E,E) λ> let r2 = (E,E,E) λ> let r3 = (E,E,E) λ> let board = (r1,r2,r3) ((E,E,E),(E,E,E),(E,E,E))
To return an updated board, I dug around and i) couldn't find a core Haskell equivalent to Clojure's update-in http://clojuredocs.org/clojure.core/update-in. ii) Zippers only deal with trees of left / right nodes. iii) So that left me with Control.Lens https://github.com/ekmett/lens/wiki/Examples. Now I can easily inspect and update the board like so.
Or you could use an two dimensional array of Positions instead (Data.Array).
λ> board^._2._1 E λ> set (_2._1) 42 board ((E,E,E),(42,E,E),(E,E,E))
I can then parameterize _2 or _1 like so.
λ> let a = _2 λ> board ^. a (E,E,E)
You can probably find the type of _1, _2, _3 in the repl, and use that in your code below.
But I can't figure out how to include that parameter's type into a Position type definition. I've tried these unsuccessfully.
data Position = Int Int deriving Show -- original type definition data Position = Simple Lens (Int a) (Int a) deriving Show -- failing try 1
These are very suspicious. Did you intend to define constructors ‘Int’ and ‘Simple’? Maybe you meant something like: data Position = Position Int Int deriving Show In which case you’ll have a type called ‘Position’ and a constructor with the same name. Cheers, Bob
move :: Board -> Piece -> Position -> Board move board piece position = set (position) piece board -- want to use this instead of "set (_2._1) 42 board"
Any ideas?
:)
Tim Washington Interruptsoftware.com http://interruptsoftware.com/
On Thu, Mar 12, 2015 at 5:18 PM, Timothy Washington
mailto:twashing@gmail.com> wrote: Veeery nice. Thanks for your insights. The Typeclass stuff making a lot more sense now. And hence ghc-mod's (Interactive-Haskell's) behaviour makes more sense to me. It's working like a charm.
I'll play around with nested list manipulation this evening.
Cheers
Tim Washington Interruptsoftware.com http://interruptsoftware.com/
On Thu, Mar 12, 2015 at 8:03 PM, Mike Meyer
mailto:mwm@mired.org> wrote: On Thu, Mar 12, 2015 at 6:02 PM, Timothy Washington mailto:twashing@gmail.com> wrote: To get started, I'm trying to implement a simple tictactoe game. And I would like to be able to represent a Piece on the board, as either the string "X" or "O". This is what I have so far. module Main where
data Piece = X | O type Row = [Piece] type Board = [Row]
-- put an X or O in a position move :: Board -> Piece -> Board move board piece = board
-- check win vertically -- check win horizontally -- check win diagonally
main :: IO () main = putStrLn "Hello World"
A) Now, I'd like to be able to load code interactively, preferably within emacs. However I don't have access to my types with ghci or ghc-mod (Interactive-Haskell). In either case, this call fails with the below error.
let p = Piece X <interactive>:20:9-13: Not in scope: data constructor `Piece'
Piece is the data TYPE. It has two constructors, X, and O. If you load your module into ghci, you can do ":t X" to get the type of X, which is Piece. You want to do "let p = X" here.
Check your mode docs while editing the haskell file. There should be a command to load the current buffer into a ghci running in an interactive emacs buffer.
B) And how do I make a custom datatype that's one of two strings (enumeration of either "X" or "O"). Cabal builds and runs the abouve code, so I know it can compile. But I'm confused as to where X or O is defined, and how I would supply it as an input.
As noted, you can derive "Show" so that Piece types print as "X" and "O". Similarly, you can derive "Read":
data Piece = X | O deriving (Show, Read)
so that you can then read "X" and get back an X when the context calls for a Piece value: *Main> read "X" :: Piece
X
However, this isn't used a lot, as it tends to be slow and not very flexible for more complex types. For instance, it will let you read in lists of Pieces and lists of lists, but you'l lhave to use the list syntax, not something that looks like an actual board when printed.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Hey man...
On Mon, Mar 23, 2015 at 4:57 AM, Bob Hutchison
Hi Tim,
Straying from clojure? :-)
Lol, love it!! I'm a free spirit. Can't hold me down :)
On Mar 22, 2015, at 12:33 PM, Timothy Washington
wrote: So I've finally had a chance to revisit my tictactoe game.
import Control.Lens
data Piece = X | O | E deriving Show type Row = [Piece] type Board = [Row] *data Position = Int Int deriving Show*
-- put an X or O in a position *move :: Board -> Piece -> Position -> Board* move board piece position = board
main :: IO () main = putStrLn "Hello World"
Now, if I want to make a move, I'll want to set a *piece* on a *position*, on a *board*. Let's assume the board has the following shape.
λ> let r1 = (E,E,E) λ> let r2 = (E,E,E) λ> let r3 = (E,E,E) λ> let board = (r1,r2,r3) ((E,E,E),(E,E,E),(E,E,E))
To return an updated board, I dug around and *i)* couldn't find a core Haskell equivalent to Clojure's update-in http://clojuredocs.org/clojure.core/update-in. *ii)* Zippers only deal with trees of left / right nodes. *iii)* So that left me with Control.Lens https://github.com/ekmett/lens/wiki/Examples. Now I can easily inspect and update the board like so.
Or you could use an two dimensional array of Positions instead (Data.Array).
Hmm, probably. But the function's type signature below, seem to be the first order of business, no?
λ> board^*._**2._1* E λ> set (*_2._1*) 42 board ((E,E,E),(42,E,E),(E,E,E))
I can then parameterize _2 or _1 like so.
λ> let a = _2 λ> board ^. a (E,E,E)
You can probably find the type of _1, _2, _3 in the repl, and use that in your code below.
The types (:t ...) of both of these are: - a :: (Field2 s t a b, Functor f) => (a -> f b) -> s -> f t - _2 :: (Field2 s t a b, Functor f) => (a -> f b) -> s -> f t
But I can't figure out how to include that parameter's type into a *Position* type definition. I've tried these unsuccessfully.
*data Position = Int Int deriving Show -- original type definition* *data Position = Simple Lens (Int a) (Int a) deriving Show -- failing try 1*
These are very suspicious. Did you intend to define constructors ‘Int’ and ‘Simple’? Maybe you meant something like:
data Position = Position Int Int deriving Show
In which case you’ll have a type called ‘Position’ and a constructor with the same name.
Cheers, Bob
So ultimately I want a function signature that lets me pass in a lens position. -- 1. these 2 don't compile together data Position = Position Int Int deriving Show move :: Board -> Piece -> Position -> Board move board piece position = set (position) piece board -- 2. and using the (:t ...) type definition abouve, none of these work move :: Board -> Piece -> ((Field2 s t a b, Functor f) => (a -> f b) -> s -> f t) -> Board -- move :: Board -> Piece -> ((a -> f b) -> s -> f t) -> Board -- move :: Board -> Piece -> (a -> f b) -> Board -- move :: Board -> Piece -> (s -> f t) -> Board move board piece position = set (position) piece board -- 3. so the below code compiles, but doesn't do me much good... I need Position to be a lens, such that I can use A) *set (position) piece board* , instead of B) *set (_2._1) 42 board* module Main where import Control.Lens data Piece = X | O | E deriving Show type Row = [Piece] type Board = [Row] *data Position = Int Int deriving Show* *move :: Board -> Piece -> Position -> Board* move board piece position = board main :: IO () main = putStrLn "Hello World" Cheers mate :) Tim Washington Interruptsoftware.com http://interruptsoftware.com/

On Mar 23, 2015, at 10:38 PM, Timothy Washington
wrote:
[snip]
So ultimately I want a function signature that lets me pass in a lens position.
-- 1. these 2 don't compile together
data Position = Position Int Int deriving Show
move :: Board -> Piece -> Position -> Board move board piece position = set (position) piece board
-- 2. and using the (:t ...) type definition abouve, none of these work
move :: Board -> Piece -> ((Field2 s t a b, Functor f) => (a -> f b) -> s -> f t) -> Board -- move :: Board -> Piece -> ((a -> f b) -> s -> f t) -> Board -- move :: Board -> Piece -> (a -> f b) -> Board -- move :: Board -> Piece -> (s -> f t) -> Board
move board piece position = set (position) piece board
-- 3. so the below code compiles, but doesn't do me much good... I need Position to be a lens, such that I can use A) set (position) piece board , instead of B) set (_2._1) 42 board
module Main where
import Control.Lens
data Piece = X | O | E deriving Show type Row = [Piece] type Board = [Row] data Position = Int Int deriving Show
move :: Board -> Piece -> Position -> Board move board piece position = board
You seem set on lenses. So if you write that move function like this (in case anyone’s wondering, I happen to know this isn’t a homework question): data Piece = X | O | E deriving Show move :: a -> b1 -> ASetter a b a1 b1 -> b move board position piece = board & position .~ piece This’ll work. But how are you going to get the position? If you’re given an integer based coordinate, as you seem to want from your definitions of Position, then you’re going to have to do something ugly. Why not just go with an array and be done with it? Something like this (with your original definition of Piece): import Data.Array data Piece' = X | O | E deriving Show type Position' = (Int,Int) type Board' = Array Position’ Piece' board' :: Board' board' = array ((1,1),(3,3)) [((i,j), E) | i <- [1,2,3], j <- [1,2,3]] move' :: Board' -> Piece' -> Position' -> Board' move' board piece pos = board // [(pos, piece)] If you want a slightly less ugly of looking at the board import qualified Data.List.Split as S pp board = mapM_ print $ S.chunksOf 3 $ elems board will display the board something like: [E,E,E] [E,E,E] [E,E,E] I hope I didn’t say too much. Cheers, Bob
main :: IO () main = putStrLn "Hello World"
Cheers mate :)
Tim Washington Interruptsoftware.com
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Crickey. You're still the man, lol :)
On Tue, Mar 24, 2015 at 6:13 AM, Bob Hutchison
On Mar 23, 2015, at 10:38 PM, Timothy Washington
wrote: [snip]
...
You seem set on lenses. So if you write that move function like this (in case anyone’s wondering, I happen to know this isn’t a homework question):
data Piece = X | O | E deriving Show
move :: a -> b1 -> ASetter a b a1 b1 -> b move board position piece = board & position .~ piece
This’ll work. But how are you going to get the position? If you’re given an integer based coordinate, as you seem to want from your definitions of Position, then you’re going to have to do something ugly.
This is a good point. I'm not particularly attached to lenses. That was just the conclusion I reached, in order to reach into and manipulate my original nested lists. I didn't see a way to do nested list updates in Data.List, on hackage https://hackage.haskell.org/package/base-4.7.0.2/docs/Data-List.html. But now I see the difference between that and Data.Array https://hackage.haskell.org/package/array-0.5.0.0/docs/Data-Array.html (indexable, etc). I'll come back to Lenses later on, just because now I'm curious. I'm happy for the Position to be "*data Position = SomeLensType SomeLensType deriving Show*", where "*:t _2 => SomeLensType*". Or something else that accommodates lens' data types.... but baby steps :) Why not just go with an array and be done with it? Something like this
(with your original definition of Piece):
import Data.Array
data Piece' = X | O | E deriving Show type Position' = (Int,Int) type Board' = Array Position’ Piece'
board' :: Board' board' = array ((1,1),(3,3)) [((i,j), E) | i <- [1,2,3], j <- [1,2,3]]
move' :: Board' -> Piece' -> Position' -> Board' move' board piece pos = board // [(pos, piece)]
This works swimmingly. So excellent point. If you want a slightly less ugly of looking at the board
import qualified Data.List.Split as S
pp board = mapM_ print $ S.chunksOf 3 $ elems board
will display the board something like:
[E,E,E] [E,E,E] [E,E,E]
I hope I didn’t say too much.
Not at all. These are exactly the kinds of hints that I need. In fact, with the *//* and *array* functions, this makes a lot of sense. And I used that and the board beautifier chunk, to create this. import Data.Array import qualified Data.List.Split as S data Piece' = X | O | E deriving Show type Position' = (Int,Int) type Board' = Array Position' Piece' board' :: Board' board' = array ((1,1),(3,3)) [((i,j), E) | i <- [1,2,3], j <- [1,2,3]] ppb' :: Board' -> IO() ppb' b = mapM_ print $ S.chunksOf 3 $ elems b move' :: Board' -> Piece' -> Position' -> Board' move' board piece pos = board // [(pos, piece)] Now, I can pass in the board, piece, and position, to get my expected result. λ> board' array ((1,1),(3,3)) [((1,1),E),((1,2),E),((1,3),E),((2,1),E),((2,2),E),((2,3),E),((3,1),E),((3,2),E),((3,3),E)] λ> let b1 = move' board' *X* (1,3) λ> b1 array ((1,1),(3,3)) [((1,1),E),((1,2),E),((1,3),X),((2,1),E),((2,2),E),((2,3),E),((3,1),E),((3,2),E),((3,3),E)] λ> ppb' b1 [E,E,*X*] [E,E,E] [E,E,E] Cheers,
Bob
Cool ! Cheers :) Tim Washington Interruptsoftware.com http://interruptsoftware.com/
participants (2)
-
Bob Hutchison
-
Timothy Washington