๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“  archive

[Haskell Tutorial] High Order Function

by HandHand 2022. 12. 31.

 

์ด๋ฒˆ ํฌ์ŠคํŠธ๋Š” http://learnyouahaskell.com/higher-order-functions ์— ๊ทผ๊ฑฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“Œ ๊ณ ์ฐจํ•จ์ˆ˜ (High Order Function)

๊ณ ์ฐจํ•จ์ˆ˜ ๋Š” ํ•จ์ˆ˜๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๊ณ , ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•œ๋งˆ๋””๋กœ ํ•จ์ˆ˜๋ฅผ ๊ฐ’์œผ๋กœ ์ทจ๊ธ‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“Œ ์ปค๋ง (Currying)

Haskell ๋‹ค์ค‘์ธ์ž ํ•จ์ˆ˜์˜ ์ •์ฒด

ํ•˜์Šค์ผˆ์˜ ํ•จ์ˆ˜๋Š” ํ•˜๋‚˜์˜ ์ธ์ž๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๋˜์–ด์žˆ๋Š”๋ฐ,

์–ด๋–ป๊ฒŒ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ผ๊นŒ์š”?

๋‘ ์ธ์ž๋ฅผ ๋ฐ›์•„ ํฐ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ max ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‘ ๋‹จ๊ณ„๋กœ ๋‚˜๋ˆ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> max 4 20
20

{- โœ… ์œ„ ํ‘œํ˜„์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. -}

ghci> maxValueWith4 = max 4
ghci> maxValueWith4 20
20

 

์œ„์™€ ๊ฐ™์ด Haskell ์—์„œ ๋‹ค์ค‘ ์ธ์ž ํ•จ์ˆ˜๋Š” ์‚ฌ์‹ค ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปค๋ง ํ•จ์ˆ˜๋กœ ๊ตฌ์„ฑ ๋ฉ๋‹ˆ๋‹ค.

 

์ปค๋ง๊ณผ ๋ถ€๋ถ„์ ์šฉ

์ปค๋ง(currying) ์€ n ๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ n๊ฐœ์˜ ๋‹จํ•ญ ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

n๊ฐœ์˜ ๋‹จํ•ญํ•จ์ˆ˜ ๊ฐ๊ฐ์€ ๊ทธ ๋‹ค์Œ ์ฒด์ธ์˜ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์„œ ๊ณ ์ฐจํ•จ์ˆ˜ ๊ฐ€ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

์ปค๋ง ์„ ํ™œ์šฉํ•˜๋ฉด ๋ถ€๋ถ„์ ์šฉ ํ†ตํ•ด์„œ n ๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ชจ๋‘ ์ œ๊ณต๋ฐ›์„ ๋•Œ๊นŒ์ง€ ์‹คํ–‰์„ ์ง€์—ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ถ€๋ถ„์ ์šฉ ์€ ํ•„์š”ํ•œ ์ธ์ž๋“ค ์ค‘ ์ผ๋ถ€๋งŒ ์ ์šฉ๋œ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ Haskell ์˜ prefix function ์„ ์˜ˆ์‹œ๋กœ ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci > :type (+3)
(+3) :: Num a => a -> a

{- ์œ„ ํ‘œํ˜„์‹์€ 3์„ ๋”ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. -}

 

์ปค๋ง๊ณผ ๋ถ€๋ถ„์ ์šฉ์˜ ์ฐจ์ด

์—„๋ฐ€ํžˆ ๋งํ•˜์ž๋ฉด ๋‘ ๊ฐœ๋…์€ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋™์ž‘๋ฐฉ์‹์— ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปค๋ง ์€ ์—„๊ฒฉํ•œ ๋ถ€๋ถ„์ ์šฉ ์˜ ํ•œ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์ปค๋ง : ์ฒด์ธ์˜ ๋‹ค์Œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ถ€๋ถ„์ ์šฉ : n๊ฐœ์˜ ์ธ์ˆ˜๋ฅผ ๊ฐ€์ง€๋Š” ํ•จ์ˆ˜์—์„œ n-m ๊ฐœ์˜ ์ธ์ˆ˜๋ฅผ ๋ฐ›๋Š” ํ•˜๋‚˜์˜ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ธ์ˆ˜๊ฐ€ ๋‘๊ฐœ๋ผ๋ฉด ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•˜๊ฒ ์ง€๋งŒ, ๊ทธ ์ด์ƒ์˜ ์ธ์ˆ˜๋ฅผ ๊ฐ€์ง€๋Š” ํ•จ์ˆ˜๋ผ๋ฉด ๋™์ž‘ ๋ฐฉ์‹์ด ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด func ์ด x, y, z ๋ผ๋Š” ์ธ์ˆ˜๋ฅผ ๋ฐ›๋Š”๋‹ค๋ฉด,

์ปค๋ง์€ 3๊ฐœ์˜ ๋‹จํ•ญ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๊ฒฐ๊ณผ์ ์œผ๋กœ func(x)(y)(z) ์˜ ์ฒด์ธ ๊ตฌ์กฐ๋กœ ํ˜ธ์ถœ๋˜๊ณ 
๋ถ€๋ถ„์ ์šฉ์€ x ๋ฅผ ์ธ์ˆ˜์—์„œ ์ œ์™ธํ•  ๊ฒฝ์šฐ func(y, z) ๋กœ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

 

์ •๋ฆฌํ•˜์ž๋ฉด, ๊ณ ์ฐจํ•จ์ˆ˜์˜ ์˜์˜๋Š”?

ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ๊ณ ์ฐจํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ณตํ†ต๋œ ํŒจํ„ด์„ ์ถ”์ƒํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์žฌ์‚ฌ์šฉ์„ฑ ์ด ๋†’์•„์ง€๋ฉฐ ๊ฐ€๋…์„ฑ ์ด ์ข‹์€ ํ•จ์ˆ˜๋ฅผ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ช…๋ นํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ๊ฐ™์€ ๋ฐฉ์‹์„ ์œ„ํ•ด์„œ ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ, ๋ณ€์ˆ˜๋“ฑ์„ ํ•จ์ˆ˜๋กœ ์ด๋ฅผ ๊ฐ์‹ธ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ๋ถ€๋ถ„์ ์šฉ ์„ ํ™œ์šฉํ•˜๋ฉด ํ˜ธ์ถœ์‹œ์ ์„ ํ•ด๋‹น ๊ฐ’์ด ํ•„์š”ํ•œ ์‹œ์ ๊นŒ์ง€ ์ง€์—ฐ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“Œ ๋žŒ๋‹ค ํ•จ์ˆ˜

๋žŒ๋‹ค ํ•จ์ˆ˜๋Š” ์ต๋ช…ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋ง ๊ทธ๋Œ€๋กœ ์ด๋ฆ„์ด ์—†๋Š” ํ•จ์ˆ˜ ์ž…๋‹ˆ๋‹ค.

Haskell ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

\x -> x + 1

 

์™œ ๋žŒ๋‹คํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ• ๊นŒ์š”?

๋žŒ๋‹คํ•จ์ˆ˜๋Š” ํŠน์ • ์ด์œ ๋กœ ํ•œ๋ฒˆ ์‚ฌ์šฉํ•˜๊ณ  ๋ง ํ•จ์ˆ˜์— ์œ ์šฉํ•˜๋ฉฐ

๋•Œ๋ฌธ์— ์ฃผ๋กœ HOF ์˜ ์ธ์ž๋กœ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ธธ๋•Œ ๋žŒ๋‹คํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๋žŒ๋‹คํ•จ์ˆ˜๊ฐ€ ์—†๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด where block ์„ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> addOneMap arr = map addOne arr where addOne x = x + 1
ghci> addOneMap [1,2,3]
[2,3,4]

 

๋žŒ๋‹คํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

addOneMap arr = map (\x -> x + 1) arr

 

๋žŒ๋‹คํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํƒ€์ž…์„ ์–ธ ํ˜•ํƒœ์™€ ๋” ๊ฐ€๊น๊ฒŒ ํ•จ์ˆ˜ ํ‘œํ˜„ํ•˜๊ธฐ

์ €์„œ์— ์†Œ๊ฐœ๋œ ๋žŒ๋‹คํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ ํฅ๋ฏธ๋กœ์šด ์˜ˆ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ธ ์ธ์ž๋ฅผ ๋”ํ•˜๋Š” ํ•จ์ˆ˜ addThree ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

addThree :: (Num a) => a -> a -> a -> a  
addThree x y z = x + y + z  

 

Haskell ์˜ ๋ชจ๋“  ํ•จ์ˆ˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ปค๋งํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์œ„ ํ‘œํ˜„์‹์€ ๋‹ค์Œ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

 

addThree :: (Num a) => a -> a -> a -> a  
addThree = \x -> \y -> \z -> x + y + z

 

๋žŒ๋‹คํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ ํ‘œํ˜„์‹์ด ํƒ€์ž…์„ ์–ธ๊ณผ ์ข€ ๋” ๊ฐ€๊นŒ์šด ํ˜•ํƒœ์ด์ง€๋งŒ, ์ฝ๊ธฐ ์‰ฌ์šด ํ˜•ํƒœ๋Š” ์ฒซ๋ฒˆ์งธ ํ‘œํ˜„์‹์ด๊ธฐ ๋•Œ๋ฌธ์—

๋ณดํ†ต ์ด๋ ‡๊ฒŒ๊นŒ์ง€ ํ‘œํ˜„ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“Œ fold ์™€ scan ํ•จ์ˆ˜

fold ์™€ scan ๋Š” ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ map, filter ์™€ ํ•จ๊ป˜ ๊ฐ€์žฅ ์ž์ฃผ ํ™œ์šฉ๋˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

๋‘ ํ•จ์ˆ˜ ๋ชจ๋‘ ์ˆœํšŒ๋ฅผ ํ•˜๋Š” ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ left side ์™€ right side ๋กœ ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค.

์ด ๋‘ ํ•จ์ˆ˜ ๋ชจ๋‘ ๋‹ค์Œ ์„ธ๊ฐ€์ง€ ์š”์†Œ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

 

  • binary function
  • starting value
  • fold ํ•  ๋Œ€์ƒ list

 

์ˆ˜ํ•™์—์„œ binary function(์ด์ง„ ํ•จ์ˆ˜) ๋ž€ ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ์„ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

 

๋ณด๋‹ค ์ •ํ™•ํžˆ ํ•ด์„ํ•˜์ž๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ์ง‘ํ•ฉ X, Y ์˜ ๋ฐ์นด๋ฅดํŠธ ๊ณฑ์˜ ๊ฒฐ๊ณผ์ธ Z ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

๋จผ์ € fold ํ•จ์ˆ˜๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

foldl, foldr ์‚ดํŽด๋ณด๊ธฐ

fold ํ•จ์ˆ˜๋Š” ๋ฆฌ์ŠคํŠธ ์ˆœํšŒ ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ foldl, foldr ๋กœ ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ foldl ์€ -> ๋ฐฉํ–ฅ, foldr ์€ <- ๋ฐฉํ–ฅ์ž…๋‹ˆ๋‹ค.

์ด ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋กœ maximum ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ์ธ์ž๋กœ ์ฃผ์–ด์ง„ ๋ฆฌ์ŠคํŠธ์˜ ์š”์†Œ ์ค‘ ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

 

ghci> maximum' (x:xs) = foldr (\x acc -> max x acc) x xs
ghci> maximum' [2, 10, 11, 4]
11

 

์•ž์„œ ์„ค๋ช…ํ•œ ๋žŒ๋‹ค ํ•จ์ˆ˜๋ฅผ foldr ์˜ binary function ์œผ๋กœ ๋„˜๊ฒจ์ฃผ๊ณ 

starting value ๋Š” ํŒจํ„ด ๋งค์นญ์„ ํ†ตํ•ด ๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ foldr1 ๋ฅผ ์ด์šฉํ•˜๋ฉด ํ•จ์ˆ˜๋ฅผ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํ•จ์ˆ˜๋Š” starting value ๋ฅผ ๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ํŒจํ„ด๋งค์นญ์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> maximum' arr = foldr1 (\x acc -> max x acc) arr

 

์•ž์„œ ์‚ดํŽด๋ณด์•˜๋“ฏ์ด max ๋˜ํ•œ ์ปค๋ง ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋žŒ๋‹คํ•จ์ˆ˜๋ฅผ ์—†์• ๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> maximum' arr = foldr1 max arr

 

์—ฌ๊ธฐ์— eta conversion ์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด point free style ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> maximum' = foldr1 max

 

๐Ÿ’ก (์ฐธ๊ณ ) eta conversion

๋žŒ๋‹ค ๋Œ€์ˆ˜(lambda calculus) ์˜ rewrite rules ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

 

 

1. \x -> abs x

{- 1. ์—์„œ 2. ๋กœ ๋ณ€ํ˜•ํ•˜๋Š” ๊ฒƒ์„ eta reduction, ๊ทธ ๋ฐ˜๋Œ€๋ฅผ eta expansion ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. -}

2. abs

 

Eta conversion

 

Eta conversion - HaskellWiki

<!-- Saved in parser cache with key wikidb_haskell:pcache:idhash:2670-0!canonical and timestamp 20221230200441 and revision id 63978 -->

wiki.haskell.org

What does eta reduce mean in the context of HLint

 

๊ทธ์™ธ์— foldl, foldr ๋ฅผ ์ด์šฉํ•œ ๋‹ค์–‘ํ•œ ์˜ˆ์‹œ

map ๊ณผ filter ๋„ fold ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

ghci> map' f = foldr (\x acc -> f x : acc) []
ghci> map' (*3) [1, 2, 3]
[3,6,9]

ghci> filter' p = foldr (\x acc -> if p x then x : acc else acc) []
ghci> filter' (>10) [11, 9, 2, 130, -1]
[11,130]
ghci> reverse' = foldr (\x acc -> acc ++ [x]) []
ghci> reverse' [1, 2, 3]
[3,2,1]

ghci> reverse' = foldl (\acc x -> x : acc) []
ghci> reverse' [1, 2, 3]
[3,2,1]

 

์—ฌ๊ธฐ์„œ foldl ์„ ํ™œ์šฉํ•œ reverse ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ•์•ฝํ• ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์™ผ์ชฝ์—์„œ๋ถ€ํ„ฐ ์ˆœํšŒํ•˜๊ธฐ ๋•Œ๋ฌธ์— binary function ์˜ ๋‘ ์ธ์ž acc ์™€ x ๋ฅผ ๋ถ™์ธ ๋‹ค์Œ,

์ด๋ฅผ ๋’ค์ง‘์œผ๋ฉด(flip) ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> reverse' = foldl (flip (:)) []

 

foldl vs foldr

foldl ๊ณผ foldr ์€ infinite list ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ด€์ ์—์„œ ์ฐจ์ด๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

[x1, x2, x3, ...] ์˜ ๋ฆฌ์ŠคํŠธ์— ํ•จ์ˆ˜ f ๋ฅผ ์ ์šฉํ•˜๊ณ  ์ดˆ๊ธฐ๊ฐ’์ด z ๋ผ๊ณ  ํ•œ๋‹ค๋ฉด,

๊ฐ๊ฐ์˜ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

 

{- foldl (left associative) -}

f ( ... (f (f (f (f z x1) x2) x3) x4) ...) xn

{- foldr (right associative) -}

f x1 (f x2 (f x3 (f x4 ... (f xn z) ... )))

 

๋‘ ํ•จ์ˆ˜ ๋ชจ๋‘ lazy ํ•˜๊ฒŒ ํ‰๊ฐ€๋œ๋‹ค๋Š” ๊ฒƒ์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋งŒ ์œ„์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด foldl ์€ ๊ฒฐ๊ณผ ๊ฐ’์„ ์–ป๊ธฐ ์œ„ํ•ด ์ค‘์ฒฉ๋œ ๋ชจ๋“  ๋ฆฌ์ŠคํŠธ๋ฅผ ํƒ์ƒ‰ํ•ด์„œ

์ตœ์ข… ํ‘œํ˜„์‹์„ ๋งŒ๋“ค์–ด์•ผํ•˜๊ธฐ์— ์ด๋Š” ๊ณณ stack overflow ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด foldr ์€ f ๊ฐ€ ์ ์šฉ๋œ ํ•˜๋‚˜์˜ ์š”์†Œ + ๋‚˜๋จธ์ง€ infinite list ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์ ์šฉ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—

๋ฌธ์ œ์—†์ด ๋™์ž‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

foldl versus foldr behavior with infinite lists

 

foldl versus foldr behavior with infinite lists

The code for the myAny function in this question uses foldr. It stops processing an infinite list when the predicate is satisfied. I rewrote it using foldl: myAny :: (a -> Bool) -> [a] -> Bool m...

stackoverflow.com

Haskell, foldr on infinite list

 

Haskell, foldr on infinite list

I got a question while reading LYAH. Here is my thought of foldr on infinite list: foldr (:) [] [1..] = 1:2:...:**∞:[]** I think GHCi does not know it is list before evaluating ∞:[]. But GHCi d...

stackoverflow.com

 

scanl, scanr ์‚ดํŽด๋ณด๊ธฐ

์ด ๋‘ ํ•จ์ˆ˜๋Š” ์•ž์„œ ์„ค๋ช…ํ•œ fold ํ•จ์ˆ˜์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฐจ์ด์ ์€ scan ํ•จ์ˆ˜๋Š” ์ค‘๊ฐ„ ๋ˆ„์ ๊ฐ’๋“ค์„ ๊ฒฐ๊ณผ ๋ฐฐ์—ด์— ํฌํ•จ์‹œ์ผœ์ค€๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

ghci> scanl (+) 0 [1, 2, 3, 4]
[0,1,3,6,10]

ghci> scanr (+) 0 [1, 2, 3, 4]
[10,9,7,4,0]

 

์ˆœํšŒ๋ฅผ ํ•˜๋Š” ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ์ตœ์ข… ๊ฒฐ๊ณผ๊ฐ’์ด ๋‹ด๊ธฐ๋Š” ์œ„์น˜๊ฐ€ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

fold ๊ณผ์ •์ด ์–ด๋–ป๊ฒŒ ์ด๋ฃจ์–ด์ง€๋Š”์ง€ ํ™•์ธํ•  ๋•Œ ์œ ์šฉํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“Œ Function application with $

Haskell ์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ํ•จ์ˆ˜๋Š” left-associative ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‹ค์Œ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๋Š” 15 ์ž…๋‹ˆ๋‹ค.

 

ghci> sqrt 4 + 4 + 9
15.0

-- ์œ„ ํ‘œํ˜„์‹์€ ๋‹ค์Œ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

ghci> (((sqrt 4) + 4) + 9)
15.0

 

๋งŒ์•ฝ 4+4+9 ์˜ ์ œ๊ณฑ๊ทผ์„ ๊ตฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ

์—ฐ์‚ฐ์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋ถ€์—ฌํ•ด์•ผํ• ๊ฒ๋‹ˆ๋‹ค.

 

ghci> sqrt (4 + 4 + 9)
4.123105625617661

 

์ด๋Ÿด๋•Œ ๊ฐ€์žฅ ๋‚ฎ์€ ์—ฐ์‚ฐ์ž ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง€๋Š” $ ๋ฅผ ์ด์šฉํ•˜๋ฉด

right-associative ํ•œ ์—ฐ์‚ฐ์„ ๊น”๋”ํ•˜๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์–‘์˜†์— ๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋™์ž‘์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> sqrt $ 4 + 4 + 9 -- โœ… ์ด๊ฑฐ๋Š” sqrt (4 + 4 + 9) ์™€ ๋™์ผํ•˜๋‹ค
4.123105625617661 -- 17 ์˜ ์ œ๊ณฑ๊ทผ

 

๐Ÿ“Œ ํ•ฉ์„ฑ ํ•จ์ˆ˜

ํ•ฉ์„ฑํ•จ์ˆ˜ ํ‘œํ˜„

ํ•ฉ์„ฑํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

 

 

์ฆ‰ ๋‘ ํ•จ์ˆ˜ g, f ๊ฐ€ ์—ฐ์‡„์ ์œผ๋กœ ํ˜ธ์ถœ๋  ๋•Œ h ๋ฅผ g ์™€ f ์˜ ํ•ฉ์„ฑํ•จ์ˆ˜ ๋ผ๊ณ  ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

Haskell ์—์„œ ํ•ฉ์„ฑํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํƒ€์ž…์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

 

ghci> :type (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

 

์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ํ•จ์ˆ˜๊ฐ€ left-associative ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์œ„ ํƒ€์ž…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

(.) :: (b -> c) -> (a -> b) -> (a -> c)

 

ํƒ€์ž…์„ ๋‹ค์‹œ ๋ณด๋ฉด 2๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ด์ง€ ์•Š๋‚˜์š”?

์ด๋ฅผ ๋„์‹ํ™”ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 

a ๋ผ๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด c ๋ผ๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ๋ฐ”๋€Œ๊ธฐ ์œ„ํ•ด

๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜ g ์™€ f ๋ฅผ ๊ฑฐ์น˜๋ฉฐ ์ด๋Š” h ๋ผ๋Š” ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง„๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํ•ฉ์„ฑํ•จ์ˆ˜์˜ ์“ฐ์ž„์ƒˆ

ํ•ฉ์„ฑํ•จ์ˆ˜๋Š” ๋žŒ๋‹คํ•จ์ˆ˜๋กœ ๋„˜๊ฒจ์ฃผ๋˜ ๊ฒƒ์„ ์ข€ ๋” ์ง๊ด€์ ์ธ ํ˜•ํƒœ ๋กœ ๋ฐ”๊พธ๋Š”๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ๋ฅผ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

ghci> map (\xs -> negate (sum (tail xs))) [[1..5],[3..6],[1..7]]  
[-14,-15,-27]

 

์ด ํ•จ์ˆ˜๋Š” ์›์†Œ ๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ(head) ๋ฅผ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ ๊ฐ’๋“ค์˜ ํ•ฉ์˜ ์Œ์ˆ˜๊ฐ’ ๋ฐฐ์—ด์„ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์ด ํ•จ์ˆ˜๋ฅผ ํ•ฉ์„ฑํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ํ•ฉ์„ฑํ•จ์ˆ˜์˜ ์ •์˜๋ฅผ ๋‹ค์‹œ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

ํ•ฉ์„ฑํ•จ์ˆ˜์˜ ํŠน์„ฑ์„ ์ด์šฉํ•ด์„œ ์šฐ๋ฆฌ๋Š” g ์— ์ ์šฉ๋˜๋Š” ์ธ์ž x ๋ฅผ ํ•ฉ์„ฑํ•จ์ˆ˜ f*โˆ˜*g ์˜ ์ธ์ž๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์œ„ ํ•จ์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> map (\xs -> (negate . sum . tail) xs) [[1..5],[3..6],[1..7]] 

 

์—ฌ๊ธฐ์— eta conversion ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋žŒ๋‹คํ•จ์ˆ˜๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด pointless style ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ghci> map (negate . sum . tail) [[1..5],[3..6],[1..7]] 

 

๐Ÿ’ก (์ฐธ๊ณ ) point free style ์ด๋ž€?

์•”๋ฌต์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ (Tacit programming) ์œผ๋กœ ๋ถˆ๋ฆฌ๋Š” ์ด ๋ฐฉ์‹์€

ํ•จ์ˆ˜ ์ •์˜๊ฐ€ ์ธ์ˆ˜๋ฅผ ์‹๋ณ„ํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ์ ์ ˆํ•œ ์ถ”์ƒํ™”๋ฅผ ์ง€์›ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ๋ณ€ํ™˜์— ์‚ฌ์šฉ๋˜๋Š” ์ธ์ž ๋Œ€์‹ ์— ๋ณ€ํ™˜ ๊ทธ ์ž์ฒด์— ์ข€ ๋” ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๋“ฑ์‹ ์ถ”๋ก  ์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ตฌ์กฐํ™”๋œ ์กฐํ•ฉ ์Šคํƒ€์ผ์„ ๊ฐ•์š”ํ•œ๋‹ค๋Š” ์žฅ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

sum lst = foldr (+) 0 lst

sum = foldr (+) 0

 

Pointfree

 

Pointfree - HaskellWiki

Pointfree Style It is very common for functional programmers to write functions as a composition of other functions, never mentioning the actual arguments they will be applied to. For example, compare: with: These functions perform the same operation, howe

wiki.haskell.org

 

โš ๏ธ ์œ ์˜ํ•  ์ 

๋‹ค๋งŒ ํ•ฉ์„ฑํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๊ฐ๊ฐ์˜ ํ•จ์ˆ˜๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ  ์ฒด์ด๋‹์ด ๊ธธ์–ด์งˆ์ˆ˜๋ก

์ด ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ์˜๋„์— ์˜ํ•ด ์ด๋ ‡๊ฒŒ ๊ธธ์–ด์ง„๊ฑด์ง€ ๋งฅ๋ฝ ํŒŒ์•…์ด ํž˜๋“ค์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ๋Š” let binding ์„ ์ด์šฉํ•˜๋ฉด ์˜๋ฏธ์žˆ๋Š” ๋” ์ž‘์€ ๋‹จ์œ„์˜ ๋ ˆ์ด๋ธ”๋ง๋œ ํ•จ์ˆ˜๋กœ ์ชผ๊ฐค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

oddSquareSum =   
    let oddSquares = filter odd $ map (^2) [1..]  
        belowLimit = takeWhile (<10000) oddSquares  
    in  sum belowLimit

 

๐Ÿ“Œ ์ฐธ๊ณ ์ž๋ฃŒ

Higher Order Functions - Learn You a Haskell for Great Good!

Anonymous function

eta conversion - Wiktionary

๋ฐ˜์‘ํ˜•

'๐Ÿ“  archive' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Haskell Tutorial] Data Type  (0) 2022.12.31
[Haskell Tutorial] Recursion  (0) 2022.12.31
[Haskell Tutorial] Module  (0) 2022.11.28
[Haskell Tutorial] Type  (0) 2022.11.28
[Haskell Tutorial] Function & Chaining  (0) 2022.11.28

๐Ÿ’ฌ ๋Œ“๊ธ€