我正在研究一个在Haskell中实现状态monad的简单示例。我使用记录语法创建了一个数据类型GlobState。函数incr1,incr2和incr3用于递增各自的记录元素。我写的代码是:
module StateExample where
import Control.Monad.State
data GlobState = GlobState { c1 :: Int, c2:: Int, c3:: Int} deriving (Show)
newGlobState:: GlobState
newGlobState = GlobState { c1=0,c2=0,c3=0 }
--incr1 :: State GlobState ()
incr1 = do
gets c1
modify (+1)
--incr2 :: State GlobState ()
incr2 = do
gets c2
modify(+1)
incr3 = do
gets c3
modify(+1)
main = do
let ((),a1) = flip runState newGlobState $ do
x<- incr1
y<- incr2 x
z<- incr1 y
return z
print a1
此程序未提供所需的输出。而且我不确定增量函数的签名或者get是否正在做我打算做的事情。请帮忙。
如何更改代码,以便不需要定义不同的增量函数,我只需要生成一个增量函数。我打算这样做:
incr :: String-> State GlobState ()
incr x = do
modify(\g -> g {x =x g + 1})
答案 0 :(得分:6)
你的类型是正确的,至少。
incr1 :: State GlobState ()
incr1 = modify (\state -> state {c1 = 1 + c1 state})
如果您在modify (+1)
工作,State Int ()
会没事的,但是我们不是。你似乎认为gets
将以下几行集中在一个特定的国家领域 - 但事实并非如此。
incr2
和incr3
需要进行类似的更改。
关于main
:
print a1
成为外部do块的一部分,但不是内部do块的一部分。如果没有缩进,编译器就无法解决这个问题。State
的整点是它的monadic / applicative管道为你做的。main = do let ((), a1) = flip runState newGlobState $ do incr1
incr2
incr1
print a1
答案 1 :(得分:3)
这里的类型是一个问题 - 在这种情况下:
modify :: (GlobState -> GlobState) -> State GlobState ()
这是一个问题,因为:
modify (+1) :: (Int -> Int) -> State Int ()
所以你需要用这样的GlobState编写你的函数:
incr1 = modify (\GlobState c1 c2 c3 -> GlobState (c1 + 1) c2 c3)
另外,您可以单独获取和设置状态:
incr1 = do
(GlobState c1 c2 c3) <- get
put (GlobState (c1 + 1) c2 c3)
答案 2 :(得分:3)
incr1 = modify c1 (+1)
incr2 = modify c2 (+1)
incr3 = modify c3 (+1)
我认为它不会比那更有意。
答案 3 :(得分:2)
这是可行的代码,也许你可以从中构建。
module StateExample where
import Control.Monad.State
data GlobState = GlobState { c1 :: Int, c2:: Int, c3:: Int} deriving (Show)
newGlobState:: GlobState
newGlobState = GlobState { c1=0,c2=0,c3=0 }
incr1 :: State GlobState ()
incr1 = modify (\g -> g {c1 = c1 g +1})
incr2 :: State GlobState ()
incr2 = do
modify (\g -> g {c2 = c2 g +1})
incr3 :: State GlobState ()
incr3 = do
modify (\g -> g {c3 = c3 g +1})
main :: IO ()
main = do
let a1 = flip execState newGlobState $ do
incr1
incr2
incr1
print a1