이 글은 위키북스 하스켈의 글을 읽고 정리한 것이다.
타입 클래스 Alternative는 Control.Applicative 모듈에 아래와 같이 정의되어 있다.
class Applicative f => Alternative f where
empty :: f a
(<|>) :: f a -> f a -> f a함수 <|>는 영어로 or 라고 발음한다.
타입 Maybe의 Alternative 인스턴스는 아래와 같이 구현되어 있다.
instance Alternative Maybe where
empty = Nothing
Nothing <|> x = x
x <|> _ = x그런데 <|>의 기능을 보면 Maybe 모노이드 중 하나인 First와 기능이 같아 보인다.
instance Semigroup (First a) where
First Nothing <> b = b
a <> _ = a
리스트 타입의 인스턴스는 아래와 같다.
instance Alternative [] where
empty = []
(<|>) = (++)함수 <|>는 주로 파싱에서 사용한다고 한다. 예를 들어 아래와 같은 함수 digit가 있다고 하자.
digit :: Int -> String -> Maybe Int
digit _ [] = Nothing
digit i (c:_)
| i > 9 || i < 0 = Nothing
| otherwise = if [c] == show i
then Just i
else Nothing함수 digit는 첫번째 인자로 넣은 숫자 i가 두번째 인자로 넣은 문자열의 첫번째 글자와 같은지 확인한다.
ghci> digit 1 "123"
Just 1
ghci> digit 1 "234"
Nothing
이제 digit와 <|>를 이용하면 동시에 두가지 조건을 파싱할 수 있다!
binChar :: String -> Maybe Int
binChar s = digit 0 s <|> digit 1 s이때 파싱 조건을 만족하는 선택지를 아래 두가지 중에서 고를 수가 있다.
0으로 시작하는 문자열1로 시작하는 문자열
This usage pattern can be described in terms of choice.
타입 클래스 MonadPlus 정의는 아래와 같다.
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a타입 제약을 제외하면 MonadPlus의 내용이 Alternative와 다를 게 없어 보인다.
항등원이나 더하기 연산이 있다는 점에서 여기서 다룬 두 타입 클래스는 Monoid와 연관이 있어 보인다.
class Monoid m where
mempty :: m
mappend :: m -> m -> minstance Monoid [a] where
mempty = []
mappend = (++)다른 점이 있다면 모노이드는 뭔가의 wrapper일 필요는 없다.