如何在状态monad中包装链式有状态计算?

时间:2015-10-08 05:47:42

标签: haskell functional-programming monads state-monad continuation-passing

我有这种格式的计算:s -> a -> s,其中s是某种状态的类型。这种功能的结果也是下一次评估的状态。例如,

appendInt :: String -> Int -> String
appendInt s i = s ++ (show i)

然后,appendInt "Int: " 1将提供"Int: 1",而(appendInt $ appendInt "Int: 1") 2将提供"Int: 12"。但是,我找不到将这种计算放在State Monad中的方法。

第一个猜测是s -> (s,s),但后来却无法传递a。然后,我尝试了(a -> s) -> (s, a -> s),但是如果没有{s则不可能a 1}}。 s -> (a,s)无效,因为a是输入而非输出。

那么我该如何包装这个计算呢? State monad是否适用于此?

2 个答案:

答案 0 :(得分:7)

您可以正常使用State,甚至可以更好地使用Writer

import Control.Monad.Writer
import Control.Monad.State

appendInt :: Int -> Writer String ()
appendInt i = tell $ show i

appendInt' :: Int -> State String ()
appendInt' i = modify (++ show i)

main = do print . execWriter $ do
            tell "Int: "
            appendInt 1
            appendInt 2
          print . flip execState "Int: " $ do
            appendInt' 1
            appendInt' 2

答案 1 :(得分:3)

当然有可能,例如:

appendIntM :: MonadState String m => Int -> m ()
appendIntM i = modify $ flip appendInt i

如果您使参数的顺序更多"传统",它只会是modify的组合。

Live On Coliru