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


83

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

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

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

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

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

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

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


그건 좋은 질문이야. 특히, Applicative그리고 MonadPlus것 같다 정확히 같은 (모듈 슈퍼 클래스 제약).
피터

1
도 있습니다 ArrowZeroArrowPlus화살. 내 생각 : 타입 시그니처를 더 깔끔하게 만드는 것 (다른 슈퍼 클래스 제약 진짜 차이 를 만든다 ).
Cat Plus Plus

2
@CatPlusPlus : 음, ArrowZero그리고 ArrowPlus종류가 * -> * -> *한 번 요구가를 사용하는 유형의 군중을 위해 그들을 사용하는 기능에 대한 화살표 유형에 전달할 수있는 수단 Monoid의 인스턴스를 요구하는 당신이 한 것 Monoid각각의 특정에 대한을 인스턴스화하고 비슷한 방식으로 처리된다는 보장이 없을 것입니다. 인스턴스가 관련이 없을 수 있습니다!
Edward KMETT 2012

답변:


120

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완전히 다른 것일 수 있습니다 (때로는 그렇습니다).


2
훌륭한 대답이지만 마지막 정의가 잘못된 것처럼 보이지만 만족스럽지 않습니다 mempty `mappend` x ≡ x.
Vitus

2
좋은 대답입니다. 있는 (일반적으로 사용) 유형의 사람을 알고 있나요 다른 MonadPlusAlternative구현을?
피터

7
@EdwardKmett :이 대답은있을 수 있음을 암시하는 것 같다 Monad이다 Alternative아니지만 MonadPlus. 나는 이것의 구체적인 예를 찾는 것에 대해 질문했다 . 당신이 알고 있다면, 나는 그것을보고 싶어요.
Antal Spector-Zabusky 2010 년

2
monadplus의 왼쪽 캐치 법칙을 설명해 주시겠습니까? []에 의해 위반 된 것으로 보입니다. 첫 번째 인수가 비어 있지 않으면 [] 실제로 두 번째 인수를 무시해야합니까?
ben w

4
@benw left 분포는 틀림없이 더 현명한 법칙이지만 일부 경우에는 적용되지 않습니다. left catch는 다른 사례가 지원하는 경향이 있지만 대부분의 다른 사례에서 지원하지 않는 대체 법칙입니다. 결과적으로, 우리는 서로 다른 인스턴스에 의해 구현되는 크게 관련되지 않은 2 개의 법칙 세트를 가지고 있습니다. 그래서 MonadPlus대부분의 사람들이 신경 쓰지 않기 때문에 실제로 두 클래스가 하나로 위장되어 있습니다.
Edward KMETT
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.