Skip to content

Instantly share code, notes, and snippets.

@nattybear
Last active November 16, 2020 10:13
Show Gist options
  • Save nattybear/b7880095df78044b8dfa3d29c0eb9c32 to your computer and use it in GitHub Desktop.
Save nattybear/b7880095df78044b8dfa3d29c0eb9c32 to your computer and use it in GitHub Desktop.
Learn You a Haskell for Great Good 14장 foldM

이 글은 책 Learn You a Haskell for Great Good을 읽고 정리한 것입니다.

foldM

함수 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"])

사랑해요 모나드 ㅎ

대문 링크

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment