使用Haskell中的State Monad访问计数

3

我有这个

newtype State' s a = State' { runState' :: (s, Counts) -> (a, s, Counts) }

现在我想要写一个函数。
getCounts :: State' s a -> Counts

有没有任何方法可以实现这个目标?


2
我猜你想要这样的东西:getCounts :: State' s Counts?(在运行状态计算之前,你不可能知道计数 - 所以你可能想从状态内部查询计数?) - Random Dev
1
@CarstenKönig 我认为更精确的写法应该是 getCounts :: State' s Counts - bheklilr
1
那么 getCounts = State' (\ (s,c) -> (c,s,c)) 怎么样? - Random Dev
1
State不是来自于Control.Monad.State吗?你可以看一下这个monad中get的实现方式,或许能够得到一些启示。 - bheklilr
1
@dosmath 如果你只是想从状态中获取 Counts,那么 Counts 是什么并不重要 - 它实际上只是另一个 s(我认为这也是 bheklilr 想说的)。 - Random Dev
显示剩余5条评论
1个回答

3
也许这就是您正在寻找的内容:
getCounts :: State' s Counts
getCounts = State' (\ (s,c) -> (c,s,c))

然后你可以在计算中使用它:

myStateComp = do
  -- whaever
  counts <- getCounts
  -- ...

是的,你也可以对它进行eval操作。

假设你的evalState'长这样:

evalState' :: State' s a -> s -> Counts -> a
evalState' st initState initCounts = 
    let (a,_,_) = runState st (initState,initCounts)
    in a

那么你可以像这样获取计数:
evalState' getCounts initState initCount

当然,这只是将initCount返回 - 但没有任何其他计算,我看不出还能回答什么其他问题。
一个真实的例子可能是这样的:
myComp = do
  -- ... do comp
  getCounts

然后

evalState' myComp initState initCount

运行任何计算并返回最后一个计数

替代方案

@bheklilr 暗示的替代方案是使用

import Control.Monad.State

type State' s a = State (s, Counts) a

并且:

myStateComp = do
  -- whaever
  (state,counts) <- get
  -- ...

因此你的getCounts实际上就是fmap snd get


好的,但是当我需要编写一个返回 (a,Counts) 的函数时,我该如何使用它呢?如果我理解正确,现在我只能在 do 块中访问 Counts? - dosmath
您可以使用初始状态来执行 eval。 - Random Dev
感谢您的回答,非常有帮助! - dosmath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接