Как обернуть цепное вычисление с сохранением состояния в монаду состояния?


У меня есть вычисления в следующем формате: 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.

Первое предположение - s -> (s,s), но затем a не может быть передано. Затем я попробовал (a -> s) -> (s, a -> s), но снова невозможно получить s Без a. s -> (a,s) не будет работа, потому что a - это вход, а не выход.

Как же мне тогда обернуть это вычисление? Подходит ли для этого монада State?

2 3

2 ответа:

Вы можете использовать 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

Конечно, это возможно, например, так:

appendIntM :: MonadState String m => Int -> m ()
appendIntM i = modify $ flip appendInt i
Если бы вы сделали порядок аргументов более "условным", это была бы просто композиция с modify.

Жить На Колиру