Search code examples
haskellfunctional-programmingmonadsstate-monadcontinuation-passing

How do I wrap a chained stateful computation in State monad?


I have computations in this format: s -> a -> s, where s is the type of some state. The result of such a function is also the state of the next evaluation. For example,

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

Then, appendInt "Int: " 1 will give "Int: 1", while (appendInt $ appendInt "Int: 1") 2 will give "Int: 12". However, I cannot find a way to put this kind of computation in a State Monad.

A first guess is s -> (s,s), but then a cannot be passed in. Then, I tried (a -> s) -> (s, a -> s), but again it is impossible to get s without a. s -> (a,s) won't work because a is the input instead of output.

How should I wrap this computation, then? Is the State monad appropriate for this?


Solution

  • You can use State just fine, or even better use 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