Skip to content

Instantly share code, notes, and snippets.

@nattybear
Last active December 19, 2020 12:19
Show Gist options
  • Save nattybear/ad79863b908a20cadc88174ce9e5b929 to your computer and use it in GitHub Desktop.
Save nattybear/ad79863b908a20cadc88174ce9e5b929 to your computer and use it in GitHub Desktop.
하스켈 타입 클래스 Alternative와 MonadPlus

이 글은 위키북스 하스켈의 글을 읽고 정리한 것이다.

Alternative

타입 클래스 AlternativeControl.Applicative 모듈에 아래와 같이 정의되어 있다.

class Applicative f => Alternative f where
  empty :: f a
  (<|>) :: f a -> f a -> f a

함수 <|>는 영어로 or 라고 발음한다.

타입 MaybeAlternative 인스턴스는 아래와 같이 구현되어 있다.

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

타입 클래스 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 -> m
instance Monoid [a] where
  mempty  = []
  mappend = (++)

다른 점이 있다면 모노이드는 뭔가의 wrapper일 필요는 없다.

대문 링크

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment