λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ“  archive

[Haskell Tutorial] Recursion

by HandHand 2022. 12. 31.

 

πŸ“Œ 반볡문 λŒ€μ‹  μž¬κ·€λ‘œ

Haskell μ—μ„œλŠ” λ°˜λ³΅μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ loop λ₯Ό μˆœνšŒν•˜λŠ” 것이 μ•„λ‹ˆλΌ μž¬κ·€ λ₯Ό ν™œμš©ν•©λ‹ˆλ‹€.

 

πŸ“Œ Tail Call Elimination

일반적으둜 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ μž¬κ·€ν˜ΈμΆœ 은 μ½œμŠ€νƒμ„ μŒ“κΈ° λ•Œλ¬Έμ— λ©”λͺ¨λ¦¬ μ΄μŠˆκ°€ λ°œμƒν•  κ°€λŠ₯성이 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ Haskell κ³Ό 같은 ν•¨μˆ˜ν˜• μ–Έμ–΄μ—μ„œλŠ” Tail-Call Elimination λ₯Ό 톡해 μ΅œμ ν™”λ₯Ό μˆ˜ν–‰ν•©λ‹ˆλ‹€.

 

πŸ“Œ Lazy Evaluation

Haskell 은 지연 평가λ₯Ό 톡해 μ‹€ν–‰λ©λ‹ˆλ‹€.

λ”°λΌμ„œ 값이 ν•„μš”ν•œ μ‹œμ μ— 평가λ₯Ό ν•˜λ©° ν•„μš”ν•˜μ§€ μ•Šλ‹€λ©΄ ν‰κ°€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

 

πŸ“Œ 예제둜 읡히기

maximum 은 리슀트의 μš”μ†Œ 쀑 κ°€μž₯ 큰 값을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.

 

maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:xs) = max x (maximum' xs)

result = maximum' [4, 5, 9, 2]
main = putStrLn (show result) -- βœ… 9

 

μ—¬κΈ°μ„œ (x:xs) λŠ” λ°°μ—΄μ˜ μš”μ†Œλ₯Ό λΆ„λ¦¬ν•˜λŠ” 자주 μ‚¬μš©λ˜λŠ” νŒ¨ν„΄μž…λ‹ˆλ‹€.

replicate λŠ” 두 개의 인자 (n, m) 을 λ°›μ•„μ„œ n을 m개 만큼 κ°€μ§€λŠ” μƒˆλ‘œμš΄ 배열을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.

 

replicate' n m
  | m <= 0 = []
  | otherwise = n:replicate' n (m-1)

result = replicate' 2 5
main = putStrLn (show result) -- [2,2,2,2,2]

 

μ—¬κΈ°μ„œ | 와 otherwise λŠ” Haskell 의 guard λ¬Έλ²•μž…λ‹ˆλ‹€.

if λ¬Έκ³Ό μœ μ‚¬ν•œλ°, 각각의 쑰건을 μ’€ 더 λͺ…ν™•ν•˜κ²Œ νŒŒμ•…ν•  수 있으며 νŒ¨ν„΄λ§€μΉ­κ³Ό ꢁ합이 μ’‹μŠ΅λ‹ˆλ‹€.

take λŠ” 두 개의 인자 x 와 arr 을 λ°›μ•„μ„œ arr μ—μ„œ x 개 반큼 μŠ¬λΌμ΄μ‹±ν•œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

 

take' n _
  | n <= 0 = []
take' _ [] = []
take' n (x:xs) = x : take' (n-1) xs

result = take' 2 [5, 4, 3, 2]
main = putStrLn (show result) -- [5,4]

 

reverse λŠ” 배열을 λ’€μ§‘λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.

 

reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]

result = reverse' [1, 2, 3, 4]
main = putStrLn (show result) -- [4, 3, 2, 1]

 

zip 은 두 배열을 λ°›μ•„μ„œ 각각의 index 둜 λ§€ν•‘λœ 배열을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.

 

zip' _ [] = []
zip' [] _ = []
zip' (x:xs) (y:ys) = [(x, y)] ++ zip xs ys

result = zip' [1, 2, 3, 4] [5, 6, 7]
main = putStrLn (show result) -- [(1,5),(2,6),(3,7)]

 

elem 은 배열에 νŠΉμ • μš”μ†Œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ νŒλ‹¨ν•˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.

 

elem' e [] = False
elem' e (x:xs)
  | e == x = True
  | otherwise = elem' e xs

result = elem' 3 [5, 6, 7]
main = putStrLn (show result) -- False

 

quicksort λŠ” 배열을 μ •λ ¬ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μž…λ‹ˆλ‹€.

Haskell 을 μ΄μš©ν•˜λ©΄ λͺ…ν™•ν•˜κ³  κ°„κ²°ν•œ λ°©μ‹μœΌλ‘œ 이 μ•Œκ³ λ¦¬μ¦˜μ„ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

Quick Sort μ˜μ‚¬μ½”λ“œ

 

quick sort λ₯Ό 짧게 μ„€λͺ…ν•˜λ©΄, pivot 을 κΈ°μ€€μœΌλ‘œ μž‘μ€ μš”μ†Œλ“€μ„ λͺ¨μ€ λ°°μ—΄ A 와

큰 μš”μ†Œλ“€λ§Œ λͺ¨μ€ B λ₯Ό λΆ„λ¦¬ν•œ λ‹€μŒ 이 μ„Έ 그룹을 ν•˜λ‚˜λ‘œ ν•©μΉœ λ’€,

pivot 을 μ œμ™Έν•œ λ‚˜λ¨Έμ§€ 두 그룹에 λŒ€ν•΄μ„œ λ™μΌν•œ λ°©μ‹μœΌλ‘œ 정렬을 ν•΄λ‚˜κ°€λŠ” λΆ„ν•  정볡 λ°©μ‹μž…λ‹ˆλ‹€.

edge-case λŠ” μ—­μ‹œ 빈 배열일 경우 μ •λ ¬ν•  ν•„μš”μ—†μ΄ [] λ₯Ό λ°˜ν™˜ν•΄μ£Όλ©΄ 될 κ²ƒμž…λ‹ˆλ‹€.

 

quicksort [] = []
quicksort (x:xs) =
  let smaller = quicksort [y | y <- xs, y < x]
      bigger = quicksort [y | y <- xs, y >= x]
  in smaller ++ [x] ++ bigger

result = quicksort [5, 1, 9, 4, 6, 7, 3]
main = putStrLn (show result) -- [1,3,4,5,6,7,9]

μ—¬κΈ°μ„œ μƒˆλ‘­κ²Œ λ“±μž₯ν•˜λŠ” 2가지 문법이 μžˆμŠ΅λ‹ˆλ‹€. 

list comprehension λŠ” 배열을 인라인으둜 μƒμ„±ν•˜λŠ” syntactic sugar μž…λ‹ˆλ‹€.

let κ³Ό in 은 ν•¨κ»˜ μ‚¬μš©ν•˜μ—¬ νŠΉμ • λ¬Έλ§₯μ—μ„œ μ‚¬μš©ν•˜λŠ” 지역 λ³€μˆ˜λ₯Ό μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

πŸ’‘ list comprehension

μ΄λŠ” 배열을 μƒμ„±ν•˜λŠ” ν•˜λ‚˜μ˜ λ°©λ²•μž…λ‹ˆλ‹€.

μ—¬κΈ°μ„œλŠ” generator 와 guard 듀을 ν•¨κ»˜ μ‚¬μš©ν•˜μ—¬ filter λ“±μ˜ λ™μž‘μ„ κ΅¬ν˜„ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

[(i, j) | i <- [1,2], j <- [1,2]] -- [(1, 1), (1, 2), (2, 1), (2, 2)]

 

πŸ“Œ μž¬κ·€μ μœΌλ‘œ μƒκ°ν•˜κΈ°

μ§€κΈˆκΉŒμ§€ μ—¬λŸ¬ μ˜ˆμ œλ“€μ„ μž¬κ·€ν•¨μˆ˜λ‘œ κ΅¬ν˜„ν•΄λ³΄λ©΄μ„œ μΌμ •ν•œ νŒ¨ν„΄μ΄ μžˆλ‹€λŠ” 것이 보일 κ²ƒμž…λ‹ˆλ‹€.

  1. κΈ°μ € μΌ€μ΄μŠ€ 생각해보기 (주둜 이미 μš°λ¦¬κ°€ 닡을 μ•Œκ³  μžˆλŠ” μΌ€μ΄μŠ€)
  2. 문제λ₯Ό μž‘κ²Œ λ§Œλ“€κΈ°
  3. μž‘μ€ λ¬Έμ œμ™€ μ›λž˜ 문제 μ‚¬μ΄μ˜ 차이 쀄이기

 

πŸ“Œ 참고자료

Substitution and Equational Reasoning

λ°˜μ‘ν˜•

'πŸ“  archive' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[Haskell Tutorial] Data Type  (0) 2022.12.31
[Haskell Tutorial] High Order Function  (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

πŸ’¬ λŒ“κΈ€