I am trying to figure out how the state Monad works. I am trying to implement a function that gets two coordinates (x, y)
and returns the x
or y
coordinate back. This should happen within the State Monad.
data Coordin = Coordin {x,y :: Float}
the functions that should be implemented they are looking like this:
getX :: State Coordin Float
getY :: State Coordin Float
How can this work out?
I have tried this:
newtype State s a = State { runState :: s -> (a,s) }
getX:: State Coordin Float
getX = State $ \(x, y) -> (x, (x, y))
but getting this error message :
Couldn't match type ‘(Float, t0)’ with ‘Coordin’
Expected type: State Coordin Float
Actual type: State (Float, t0) Float
In the expression: State $ \ (x, y) -> (x, (x, y))
In an equation for ‘getX’: getX = State $ \ (x, y) -> (x, (x, y))
State $ \(x, y) -> (x, (x, y))
has the type State (Float,Float) Float
, which is indeed equivalent (isomorphic) to State Coordin Float
, but it's not literally the same type. The Coordin
type must be unwrapped with the Coordin
constructor, not with the tuple constructor!
getX :: State Coordin Float
getX = State $ \(Coordin x y) -> (x, Coordin x y)
Alternatively, and preferrably, you can use the record field accessor:
getX = x <$> get