Turtle Graphics as a Haskell Monad

Posted by iliis on Stack Overflow See other posts from Stack Overflow or by iliis
Published on 2012-11-11T13:01:22Z Indexed on 2012/11/11 17:00 UTC
Read the original article Hit count: 373

Filed under:
|
|

I'm trying to implement turtle graphis in Haskell. The goal is to be able to write a function like this:

draw_something = do
    fordward 100
    right 90
    forward 100
    ...

and then have it produce a list of points (maybe with additional properties):

> draw_something (0,0) 0        -- start at (0,0) facing east (0 degrees)
[(0,0), (0,100), (-100,100), ...]

I have all this working in a 'normal' way, but I fail to implement it as a Haskell Monad and use the do-notation. The basic code:

data State a = State (a, a) a -- (x,y), angle
    deriving (Show, Eq)

initstate :: State Float
initstate = State (0.0,0.0) 0.0


-- constrain angles to 0 to 2*pi
fmod :: Float -> Float
fmod a 
    | a >= 2*pi = fmod (a-2*pi)
    | a <  0    = fmod (a+2*pi)
    | otherwise = a

forward :: Float -> State Float -> [State Float]
forward d (State (x,y) angle) = [State (x + d * (sin angle), y + d * (cos angle)) angle]

right :: Float -> State Float -> [State Float]
right d (State pos angle) = [State pos (fmod (angle+d))]


bind :: [State a] -> (State a -> [State a]) -> [State a]
bind xs f = xs ++ (f (head $ reverse xs))

ret :: State a -> [State a]
ret x = [x]

With this I can now write

> [initstate] `bind` (forward 100) `bind` (right (pi/2)) `bind` (forward 100)                                                                     
[State (0.0,0.0) 0.0,State (0.0,100.0) 0.0,State (0.0,100.0) 1.5707964,State (100.0,99.99999) 1.5707964]

And get the expected result. However I fail to implement this as an instance of Monad.

instance Monad [State] where
    ...

results in

`State' is not applied to enough type arguments
Expected kind `*', but `State' has kind `* -> *'
In the instance declaration for `Monad [State]'

And if I wrap the list in a new object

data StateList a = StateList [State a]

instance Monad StateList where
    return x = StateList [x]

I get

    Couldn't match type `a' with `State a'                                                                                                             
      `a' is a rigid type variable bound by                                                                                                            
          the type signature for return :: a -> StateList a at logo.hs:38:9                                                                            
    In the expression: x                                                                                                                               
    In the first argument of `StateList', namely `[x]'                                                                                                 
    In the expression: StateList [x]

I tried various other versions but I never got it to run as I'd like to. What am I doing wrong? What do I understand incorrectly?

© Stack Overflow or respective owner

Related posts about haskell

Related posts about monads