이 글은 Learn You a Haskell for Great Good 중 일부를 정리한 것이다.
타입 Ordering
은 뭔가 비교한 결과를 표현할 때 쓴다. Ordering
에는 값이 세 개 있다.
data Ordering =
LT
| EQ
| GT
LT
: Less ThanEQ
: EqualGT
: Greater Than
아래와 같이 함수 compare
로 두 수를 비교하면 결과로 타입 Ordering
의 값 중 하나가 나온다.
ghci> 1 `compare` 2
LT
ghci> 2 `compare` 2
EQ
ghci> 3 `compare` 2
GT
세미그룹과 모노이드 인스턴스는 아래와 같다.
instance Semigroup Ordering where
LT <> _ = LT
EQ <> y = y
GT <> _ = GT
instance Monoid Ordering where
mempty = EQ
mappend = (<>)
- 항등원은
EQ
이다. <>
에 먼저 들어온 것이EQ
일 경우 나중에 들어온 것이 결과가 된다.- 그렇지 않을 때는 그냥 먼저 들어온 것이 결과가 된다.
두 문자열의 길이를 비교해서 결과로 타입 Ordering
이 나오는 함수를 만들어 보자. 그런데 만약 길이가 같으면 알파벳 순으로 크기를 결정한다.
lengthCompare :: String -> String -> Ordering
lengthCompare x y =
let a = length x `compare` length y
b = x `compare` y
in if a == EQ then b else a
a
는 길이를 비교한 결과b
는 알파벳순으로 비교한 결과- 길이가 같으면
b
가 결과가 되고 그렇지 않으면a
가 결과가 된다.
Ordering
도 모노이드라는 점을 이용하면 아래와 같이 더 쉽게 할 수 있다.
lengthCompare x y =
(length x `compare` length y)
<> (x `compare` y)
ghci> lengthCompare "zen" "ants"
LT
ghci> lengthCompare "zen" "ant"
GT
Ordering
모노이드는 먼저 오는 것이 EQ
가 아니라면 먼저 온 것이 결과가 된다. 따라서 위와 같이 여러 조건을 우선 순위에 따라 비교하고 싶을 때 더 중요하다고 생각하는 조건을 맨 앞에 두면 된다.
위 예제에서 검사 조건을 하나 더 추가해보자. 이번에는 문자열 중 모음의 개수를 두 번째 조건으로 추가한다.
lengthCompare x y =
(length x `compare` length y)
<> (vowels x `compare` vowels y)
<> (x `compare` y)
where vowels = length . filter (`elem` "aeiou")
함수 vowels
는 문자열을 입력하면
- 문자열에서
"aeiou"
에 속하는 글자만filter
로 골라내고 - 그 길이가 결과로 나온다.
ghci> lengthComapre "zen" "anna"
LT
ghci> lengthComapre "zen" "ana"
LT
ghci> lengthCompare "zen" "ann"
GT