The state monad and learnyouahaskell.com
The accepted answer already mentions to use the state
function from Control.Monad.State
rather than the State
type. However, if you simply try the accepted answer in ghci
with the associated mtl
package loaded, it will still fail:
Prelude Control.Monad.State> push a = state $ \xs -> ((), a:xs)
<interactive>:5:1: error:
• Non type-variable argument in the constraint: MonadState [a] m
(Use FlexibleContexts to permit this)
• When checking the inferred type
push :: forall a (m :: * -> *). MonadState [a] m => a -> m ()
To resolve this, there are two options here:
- Either specify the type signature for the function (which you should anyways).
- Add the
FlexibleContexts
compiler extension, as mentioned in the error.
We can specify the type signature:
module LearnYouAHaskell where
import Control.Monad.State as State
push :: Int -> State.State [Int] ()
push a = State.state $ \xs -> ((), a:xs)
The above compiles fine and functions as expected.
Or we can add the language extension so it can infer the function type.
{-# LANGUAGE FlexibleContexts #-}
module LearnYouAHaskell where
import Control.Monad.State as State
push a = State.state $ \xs -> ((), a:xs)
Which will also work fine.
As I mentioned in comments, you ought to use state
instead of State
.
The problem is that State
is not standalone data type (or rather newtype
), but it is the StateT
transformer applied to Identity
monad. Actually, it's defined as
type State s = StateT s Indentity
and because it's just type
synonym, it cannot have State
constructor. That's why Control.Monad.State
uses state
.