뭔가 새로운 것을 공부할 때는 그것을 직접 구현해보는 것이 도움이 된다.
하스켈 함수 filter
는 어려운 개념은 아니지만 이 시리즈가 글쓰기 좋은 소재가 될 것 같아서 쉬운 것부터 시작해본다.
아래 글은 DIY 예찬에 대해 페이스북에 올렸던 글이다.
읽고 있는 하스켈 책에 아래와 같은 권유가 있었다.
While reading this section, try to write definition of each list function once its description has been introduced. Doing so is a good exercise to cement the concepts of parametric polymorphism and higher-order functions in your mind. You can start by writing the
filter
function.
별 거 아니지만 이렇게 책을 읽다보면 평소에는 생각하지 못했던 글쓰기 소재가 떠오르곤 한다.
함수 filter
는 map
과 함께 함수형 프로그래밍의 빵과 버터 같은 존재라고 한다. 파이썬에도 내장 함수로 있을 정도이고 함수를 인자로 받는 함수를 소개하기에 시작으로 참 좋다.
사용 예를 먼저 보자. shut up and show me the code
GHCi> filter even [1..10]
[2,4,6,8,10]
보면 알겠지만 함수 filter
는 첫번째 인자로 타입이 a -> Bool
인 함수를 받고 두번째 인자로는 리스트를 받는다. 리스트의 원소 중 첫번째 인자로 받은 함수에 적용했을 때 결과가 참인 것만 골라주는 편리한 함수이다.
타입은 아래와 같다.
filter :: (a -> Bool) -> [a] -> [a]
하스켈 타입 코드는 타이핑 하는 일 자체가 뭔가 그냥 즐겁다.
코드 구현은 아래와 같을 것 같다. 나중에 소스코드도 한번 들여다보자.
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter f (x:xs) = if f x
then x : filter f xs
else filter f xs
Hoogle에서 확인한 실제 소스코드는 아래와 같다. 내가 구현한 것과는 다르게 Guard를 사용했다.
filter :: (a -> Bool) -> [a] -> [a]
filter _pred [] = []
filter pred (x:xs)
| pred x = x: filter pred xs
| otherwise = filter pred xs
하스켈 소스코드에서는 사용하지 않는 함수를 나타낼 때 그냥 _
를 쓰지 않고 _pred
처럼 이름 앞에 _
를 붙인 점이 눈에 띈다.