在阅读了几本关于Haskell状态monad的教程后,我想自己尝试一下。我读过的教程声称Control.Monad.State提供了以下定义:
newtype State s a = State { runState :: s -> (a,s) }
但是,我似乎无法找到State
数据构造函数:
Prelude> import Control.Monad.State
Prelude Control.Monad.State> :t State
<interactive>:1:1:
Not in scope: data constructor `State'
Perhaps you meant `StateT' (imported from Control.Monad.State)
我还尝试了对State
进行Hoogle搜索,但未找到任何具有预期类型的数据构造函数。
State
构造函数去了哪里?它曾经存在过吗?或者我只是在错误的地方寻找?基本上我想知道我需要做什么来创建状态monad。
答案 0 :(得分:30)
它不再存在。不幸的是,这使得Web上的许多Haskell资源都过时了。
要创建值,您只需使用state
函数:
state :: (s -> (a, s)) -> State s a
runState
,曾经是State
的字段,现在只是一个普通的函数,但它的工作原理和以前一样。
State
已根据StateT
monad变换器重写:
type State s = StateT s Identity
StateT
本身有一个构造函数StateT
,其功能与旧的State
构造函数非常相似:
newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }
唯一的区别是有一个额外的参数m
。这只是一个插槽,您可以在其中添加任何其他monad,StateT
然后使用状态处理功能进行扩展。当然,要重新获得State
的旧功能,您只需将m
设置为Identity
,这样做无效。
newtype Identity a = Identity { runIdentity :: a }
答案 1 :(得分:14)
前一段时间MTL已从
切换newtype State s a = State ...
到
type State s = StateT s Identity
因为否则我们不得不复制每个monad及其变换器的逻辑。相反,您现在可以使用state
函数
state :: (s -> (a, s)) -> State s a
答案 2 :(得分:4)
我正在通过Learn Has a Haskell(LYAH)进行学习,我认为我会发布在http://learnyouahaskell.com/for-a-few-monads-more#state(第13章,“有状态的有状态计算”一节)中找到的示例代码的工作版本。 >
不再起作用的代码:
import Control.Monad.State
pop :: State Stack Int
pop = State $ \(x:xs) -> (x,xs)
push :: Int -> State Stack ()
push a = State $ \xs -> ((),a:xs)
修改后的代码可以正常工作:
import Control.Monad.State
pop :: State Stack Int
-- note the change from "State" to "state"
pop = state $ \(x:xs) -> (x,xs)
push :: Int -> State Stack ()
push a = state $ \xs -> ((), a:xs)
“ stackManip”函数按原样工作:
stackManip :: State Stack Int
stackManip = do
push 3
a <- pop
pop