Folding in Haskell

Β· 1077 words Β· 3 minute read

Folding in Haskell πŸ”—

취업을 μœ„ν•œ 포트폴리였 μ€€λΉ„ μž‘μ—…μœΌλ‘œ λ°”μœ κ°€μš΄λ°, Functional Programming에 λŒ€ν•΄ 관심이 생겨 Haskellμ΄λΌλŠ” μ–Έμ–΄λ₯Ό 배우기 μ‹œμž‘ν–ˆλ‹€. (μ•Œκ³ λ¦¬μ¦˜μ΄λ‚˜ λ°μ΄ν„°λ² μ΄μŠ€ λ“± 배울 것이 λ§Žμ€ 데 갈수둝 νƒœμ‚°μ΄λ‹€.) λŒ€ν•™κ΅ μ‹œμ ˆ, xmonad μœˆλ„μš°μ¦ˆ λ§€λ‹ˆμ €λ₯Ό μ‚¬μš©ν•˜λ©΄μ„œ μ ‘ν•œ μ–Έμ–΄λ₯Ό μ΄λ ‡κ²Œ λ’€λŠ¦κ²Œ 배우게 될 쀄은 κΏˆμ—λ„ λͺ°λžλ‹€.

λŒ€ν‘œμ μΈ ν•¨μˆ˜ν˜• μ–Έμ–΄λ‘œ μ•Œλ €μ§„ Haskell μ—λŠ” Folding μ΄λΌλŠ” νŠΉλ³„ν•œ κ°œλ…μ΄ λ“±μž₯ν•œλ‹€. Haskell Wikiμ—μ„œλŠ” Folding을 μ•„λž˜μ™€ 같이 μ„€λͺ…ν•˜κ³  μžˆλ‹€.

In functional programming, fold (or reduce) is a family of higher order functions that process a data structure in some order and build a return value.
Typically, a fold deals with two things: a combining function, and a data structure (typically a list of elements). The fold then proceeds to combine elements of the data structure using the function in some systematic way.

λ¦¬μŠ€νŠΈμ™€ 같이 μ—¬λŸ¬ μ›μ†Œλ“€λ‘œ 이루어진 데이터 ꡬ쑰의 각 μ›μ†Œλ“€μ„ 각각 인자(arguments)둜 λ„˜κΈ΄ ν•¨μˆ˜μ— λŒ€μž…ν•˜κ³ , κ·Έ κ²°κ³Όλ₯Ό μ›μ†Œ νƒ€μž…μœΌλ‘œ λ°˜ν™˜ν•˜λŠ” 것이 fold ν•¨μˆ˜μ˜ 역할이닀. λ‹€μ‹œ λ§ν•΄μ„œ, spine ν˜•νƒœμ˜ 데이터 ꡬ쑰λ₯Ό νŠΉμ •ν•œ ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ μ ‘κ³ (fold) μ€„μ—¬μ„œ(reduce) 결과값을 μ–»λŠ” 것이 κ·Έ 역할이라고 μ •λ¦¬ν•˜λ©΄ μ΄ν•΄ν•˜κΈ° 쉽닀.

λ¨Όμ €, μ•„λž˜μ˜ 예제λ₯Ό μ‚΄νŽ΄λ³΄μž.

> foldr (+) 1 [1..3]
7

> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b

foldr은 (a -> b -> b) ν˜•νƒœμ˜ ν•¨μˆ˜μ™€ b, t a 인자 3 개λ₯Ό μž…λ ₯ λ°›μ•„ b νƒ€μž…μ„ λ°˜ν™˜ν•œλ‹€. 즉, (1 + (2 + (3 + (1))) κ³Ό 같은 ν˜•μ‹μœΌλ‘œ fold λ₯Ό μ§„ν–‰ν•˜μ—¬ κ²°κ΅­ 닡은 7이 λœλ‹€. 이 λ•Œ, 각 κ΄„ν˜Έλ₯Ό reduceν•œ κ²°κ³ΌλŠ” foldr λŒ€μ‹  scanr ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μ•„λž˜μ™€ 같이 얻을 수 μžˆλ‹€.

> scanr (+) 1 [1..3]
[7,6,4,1]

κ·Έλ ‡λ‹€λ©΄, λ°˜λŒ€λ‘œ κ΄„ν˜Έλ₯Ό 움직여 evaluation의 λ°©ν–₯을 μ™Όμͺ½μ—μ„œ 였λ₯Έμͺ½μœΌλ‘œ 바꿔보면 μ–΄λ–¨κΉŒ?

> foldl (+) 1 [1..3]
7
> scanl (+) 1 [1..3]
[1,2,4,7]
> :t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b

foldrκ³Ό 달리 foldr은 μ „λ‹¬ν•œ ν•¨μˆ˜μ— 인자둜 (a -> b -> b)κ°€ μ•„λ‹Œ (b -> a -> b)λ₯Ό μ „λ‹¬ν•œλ‹€. 이 λ•Œλ¬Έμ— 결과값은 같더라도 평가(Evaluation)의 μˆœμ„œκ°€ ((((1) + 1) + 2) + 3) λ‹¬λΌμ§€κ²Œ λœλ‹€. 이 λ•Œλ¬Έμ— scanl의 κ²°κ³ΌλŠ” [1,2,4,7]이 λ˜λŠ” 것이닀.

μ΄λŸ¬ν•œ fold의 μž₯점은 갖가지 μž¬κ·€ ν•¨μˆ˜λ“€μ„ μ—„μ²­λ‚˜κ²Œ κ°„λ‹¨ν•˜κ²Œ λ§Œλ“€ 수 μžˆλ‹€λŠ” 것이닀. 예λ₯Ό λ“€λ©΄, reverse ν•¨μˆ˜μ˜ 경우 보톡 μ•„λž˜μ™€ 같이 μž‘μ„±ν•  수 μžˆλ‹€.

myReverse :: [a] -> [a]
myReverse [] = []
myReverse (x:xs) = myReverse xs ++ [x]

ν•˜μ§€λ§Œ, foldλ₯Ό μ‚¬μš©ν•˜λ©΄, μ•„λž˜μ™€ 같이 μΆ•μ•½λœ ν˜•νƒœλ‘œ κ°„λ‹¨ν•˜κ²Œ μž‘μ„±ν•  수 μžˆλ‹€.

-- pointfree ν•¨μˆ˜ ν˜•νƒœλ‘œ μž‘μ„±
myReverse :: [a] -> [a]
myReverse = foldl (flip (:)) []

이처럼 ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œ fold λ˜λŠ” reduceλŠ” 인자둜 μ „λ‹¬ν•œ 데이터 ꡬ쑰λ₯Ό νŠΉμ •ν•œ ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ λ°˜ν™˜κ°’μ„ κ΅¬μ„±ν•˜κΈ° μœ„ν•œ HOF (Higher Order Functions, ν•¨μˆ˜λ₯Ό 인자둜 μ·¨ν•˜κ±°λ‚˜ λ°˜ν™˜κ°’μœΌλ‘œ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜)의 ν•œ 가지이닀. λ¬Έμ„œ λŒ€λΆ€λΆ„μ΄ μ˜μ–΄λ‘œ λ˜μ–΄ 있고 ν•¨μˆ˜ν˜• 언어에 λŒ€ν•΄μ„œλŠ” μ•„μ§κΉŒμ§€ 관심을 κ°€μ§€λŠ” μ‚¬λžŒμ΄ 많이 μ—†μ–΄ κ³΅λΆ€ν•˜κΈ°μ—λŠ” 쉽지 μ•Šμ§€λ§Œ ν•˜λ‚˜μ”© 정리해 λ‚˜κ°€λ‹€ 보면 μ–Έμ  κ°€λŠ” λ¬Έμ„œλ₯Ό λ§Œλ“€ 수 μžˆμ„ μ •λ„λ‘œ μžλ£Œκ°€ λ§Žμ•„μ§ˆ 것이라 κΈ°λŒ€ν•œλ‹€.