我正在阅读Learn You a Haskell's guide on the state monad,但我无法理解它,因为堆栈示例无法编译。在指南中,他使用了以下代码:
import Control.Monad.State
type Stack = [Int]
pop :: State Stack Int
pop = State $ \(x:xs) -> (x,xs)
push :: Int -> State Stack ()
push a = State $ \xs -> ((),a:xs)
虽然我理解它应该做什么,但它不会编译。我不知道为什么。错误消息是:
Stack.hs:6:7: Not in scope: data constructor `State'
Stack.hs:9:10: Not in scope: data constructor `State'
这对我没有意义,因为据我所知,“State”实际上是一个数据构造函数,定义为
newtype State s a = State { runState :: s -> (a,s) }
指南是“错误的”,如果是,我该如何解决?
答案 0 :(得分:0)
已接受的答案已经提到使用state
中的Control.Monad.State
函数而不是State
类型。但是,如果您只是在ghci
中加载了相关的mtl
软件包,尝试使用已接受的答案,则它仍然会失败:
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 ()
要解决此问题,这里有两个选项:
FlexibleContexts
编译器扩展。我们可以指定类型签名:
module LearnYouAHaskell where
import Control.Monad.State as State
push :: Int -> State.State [Int] ()
push a = State.state $ \xs -> ((), a:xs)
上面的代码可以正常编译和运行。
或者我们可以添加语言扩展名,以便它可以推断函数类型。
{-# LANGUAGE FlexibleContexts #-}
module LearnYouAHaskell where
import Control.Monad.State as State
push a = State.state $ \xs -> ((), a:xs)
哪个也可以正常工作。