[haskell] 유형 클래스 MonadPlus, Alternative 및 Monoid의 차이점은 무엇입니까?

표준 라이브러리 Haskell typeclasses MonadPlus, AlternativeMonoid각각은 본질적으로 동일한 의미를 가진 두 가지 메서드를 제공합니다.

  • 빈 값 : mzero, empty, 또는 mempty.
  • 운영자 a -> a -> a: 함께 typeclass 값을 결합 mplus, <|>또는 mappend.

세 가지 모두 인스턴스가 준수해야하는 다음 법률을 지정합니다.

mempty `mappend` x = x
x `mappend` mempty = x

따라서 세 가지 유형 클래스가 모두 동일한 메서드를 제공하는 것 같습니다 .

( 및 Alternative을 제공 하지만 일반적으로 기본 정의로 충분하므로이 질문과 관련하여 너무 중요하지 않습니다.)somemany

그래서, 내 질문은 : 왜이 ​​세 가지 매우 유사한 클래스가 있습니까? 서로 다른 수퍼 클래스 제약 사항 외에 실제 차이점이 있습니까?



답변

MonadPlusMonoid다른 목적을 제공합니다.

A Monoid는 종류 유형에 대해 매개 변수화 *됩니다.

class Monoid m where
    mempty :: m
    mappend :: m -> m -> m

따라서 연관성이 있고 단위가있는 명백한 연산자가있는 거의 모든 유형에 대해 인스턴스화 될 수 있습니다.

그러나, MonadPlus당신이 모노 이드 구조를 가지고 있음을 명시 할뿐만 아니라 그 구조가 Monad작동 방식과 관련이 있고 그 구조가 모나드에 포함 된 값을 신경 쓰지 않는다는 것을 명시합니다. 이것은 (부분적으로) 사실로 표시됩니다. 그 MonadPlus종류의 인수를 사용합니다 * -> *.

class Monad m => MonadPlus m where
    mzero :: m a
    mplus :: m a -> m a -> m a

모노 이드 법칙 외에도 적용 할 수있는 두 가지 잠재적 법칙이 있습니다 MonadPlus. 슬프게도 커뮤니티는 그들이되어야하는 것에 대해 동의하지 않습니다.

적어도 우리는 알고 있습니다

mzero >>= k = mzero

그러나 두 가지 다른 경쟁 확장이 있습니다.

mplus a b >>= k = mplus (a >>= k) (b >>= k)

그리고 좌익 법

mplus (return a) b = return a

따라서의 모든 사례는 MonadPlus이러한 추가 법률 중 하나 또는 둘 다를 충족해야합니다.

그래서 Alternative어때?

Applicative은 이후에 정의 Monad되었고 논리적으로의 수퍼 클래스로 속합니다 Monad.하지만 대체로 Haskell 98에서 디자이너에 대한 압력이 다르기 때문에 2015 년까지는 Functor수퍼 클래스가 아니 었습니다 Monad. 이제 우리는 마침내 GHC에서 Applicative의 수퍼 클래스가 Monad되었습니다. 아직 언어 표준입니다.)

실제로 AlternativeApplicative무엇 MonadPlus에 대한 것 Monad입니다.

이것들을 위해 우리는 얻을 것입니다

empty <*> m = empty

우리가 가지고있는 것과 유사 MonadPlus하며 유사한 분배 및 캐치 속성이 존재하며, 그중 적어도 하나는 만족해야합니다.

불행히도 empty <*> m = empty법률 조차도 너무 강력한 주장입니다. 예를 들어 Backwards 에는 적용되지 않습니다 !

MonadPlus를 보면 빈 >> = f = 빈 법칙이 거의 우리에게 강요됩니다. 빈 구조는 f어쨌든 함수를 호출하기 위해 ‘a’를 가질 수 없습니다 .

때문에, Applicative있다 없다 의 슈퍼 클래스 MonadAlternative하지 의 슈퍼 클래스 MonadPlus, 우리는 별도로 두 인스턴스를 정의하는 바람.

더군다나 Applicative의 슈퍼 클래스였다 하더라도 어쨌든 클래스 Monad가 필요 MonadPlus하게 될 것입니다.

empty <*> m = empty

그것은 증명하기에 충분하지 않습니다.

empty >>= f = empty

그래서 무언가가 a MonadPlus라고 주장하는 것은 그것이 있다고 주장하는 것보다 더 강합니다 Alternative.

이제 규칙에 따라 MonadPlus그리고 Alternative해당 유형에 대한 동의한다, 그러나이 Monoid될 수있다 완전히 다른.

예를 들어 MonadPlusand Alternativefor Maybe는 명백한 일을합니다.

instance MonadPlus Maybe where
    mzero = Nothing
    mplus (Just a) _  = Just a
    mplus _        mb = mb

그러나 Monoid인스턴스는 세미 그룹을 Monoid. 안타깝게도 SemigroupHaskell 98에는 당시에 클래스가 없었기 때문에를 요구 Monoid하지만 그 단위를 사용하지 않고 있습니다. ಠ_ಠ

instance Monoid a => Monoid (Maybe a) where
    mempty = Nothing
    mappend (Just a) (Just b) = Just (mappend a b)
    mappend Nothing x = x
    mappend x Nothing = x
    mappend Nothing Nothing = Nothing

TL; DR MonadPlus 은보다 강력한 클레임이며 Alternative, 이는 차례로보다 강력한 클레임이며 유형 MonoidMonadPlusAlternative인스턴스는 관련되어야하지만 Monoid완전히 다른 것일 수 있습니다 (때로는 그렇습니다).


답변