이 글은 책 Learn You a Haskell for Great Good을 읽고 정리한 것입니다.
함수 foldl
의 모나드 버전은 foldM
이다. foldl
의 타입은 아래와 같다.
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl
의 인자와 결과는 순서대로 아래와 같다.
(a -> b -> a)
: 인자가 두개인 함수a
: 결과를 누적할 초기값[b]
:fold
를 수행할 리스트
아래와 같이 사용할 수 있다.
GHCi> foldl (\acc x -> acc + x) 0 [2,8,3,1]
14
foldM
의 타입은 아래와 같다.
foldM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
foldM
의 타입은 foldl
와 비슷한데 첫번째 인자로 받는 함수의 결과 타입과 최종 결과 타입만 m a
로 다르다.
리스트의 원소 값이 9
보다 크면 실패한다는 Maybe
문맥을 추가해보자. 아래와 같이 함수 binSmalls
를 정의할 수 있다.
binSmalls :: Int -> Int -> Maybe Int
binSmalls acc x
| x > 9 = Nothing
| otherwise = Just (acc + x)
아래와 같이 foldM
을 이용할 수 있다.
GHCi> foldM binSmalls 0 [2,8,3,1]
Just 14
GHCi> foldM binSmalls 0 [2,11,3,1]
Nothing
책에서 제시한 예제는 여기까지이고 아래와 같이 'Writer
값을 리턴하는 함수를 이용하면 재밌을 것이다' 라고 적혀있다.
Folding with a binary function that returns a
Writer
value is cool as well, because then you log whatever you want as your fold goes along its way.
한번 만들어보자.
binLog :: Int -> Int -> Writer [String] Int
binLog acc x = (acc + x, ["add " ++ show x ++ " to " ++ show acc])
GHCi> foldM binLog 0 [1,2,3,4]
GHCi> runWriter $ foldM f 0 [1,2,3,4]
(10,["add 1 to 0","add 2 to 1","add 3 to 3","add 4 to 6"])
사랑해요 모나드 ㅎ