State

例: State モナドで mapAccumL

mapAccumL は状態を持った map 関数です。累積和を計算してみます:

#!/usr/bin/env stack import Data.List main :: IO () main = do -- 数列 → 累積和 -- [1, 2, 3] -> (6, [1, 3, 6]) print $ mapAccumL (\acc x -> (acc + x, acc + x)) (0 :: Int) [1, 2, 3] -- 累積和 → 数列 -- [1, 3, 6] -> (6, [1, 2, 3]) print $ mapAccumL (\lastX x -> (x, x - lastX)) (0 :: Int) [1, 3, 6]

累積和の計算には fold を使うことができます。しかし累積和を数列に戻す際には mapAccumL を使うしかないと思います。

同様の計算は mapMState モナドにより表現可能です:

#!/usr/bin/env stack import Control.Monad.State import Data.List main :: IO () main = do -- 数列 → 累積和 -- [1, 2, 3] -> ([1, 3, 6], 6) print $ runState (mapM (\x -> state $ \acc -> (x + acc, x + acc)) [1, 2, 3]) (0 :: Int) -- 累積和 → 数列 -- [1, 3, 6] -> ([1, 2, 3], 0) print $ runState (mapM (\x -> state $ \lastX -> (x - lastX, x)) [1, 2, 3]) (0 :: Int)

mapAccumLTraversable なデータ型にしか適用できませんが、mapM なら Vector に対しても適用できます。

例: do 記法

TODO: ポイントフリースタイルの恩恵

TODO: パフォーマンスへの (悪) 影響