표준 라이브러리 Haskell typeclasses MonadPlus
, Alternative
및 Monoid
각각은 본질적으로 동일한 의미를 가진 두 가지 메서드를 제공합니다.
- 빈 값 :
mzero
,empty
, 또는mempty
. - 운영자
a -> a -> a
: 함께 typeclass 값을 결합mplus
,<|>
또는mappend
.
세 가지 모두 인스턴스가 준수해야하는 다음 법률을 지정합니다.
mempty `mappend` x = x
x `mappend` mempty = x
따라서 세 가지 유형 클래스가 모두 동일한 메서드를 제공하는 것 같습니다 .
( 및 Alternative
을 제공 하지만 일반적으로 기본 정의로 충분하므로이 질문과 관련하여 너무 중요하지 않습니다.)some
many
그래서, 내 질문은 : 왜이 세 가지 매우 유사한 클래스가 있습니까? 서로 다른 수퍼 클래스 제약 사항 외에 실제 차이점이 있습니까?
답변
MonadPlus
및 Monoid
다른 목적을 제공합니다.
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
되었습니다. 아직 언어 표준입니다.)
실제로 Alternative
는 Applicative
무엇 MonadPlus
에 대한 것 Monad
입니다.
이것들을 위해 우리는 얻을 것입니다
empty <*> m = empty
우리가 가지고있는 것과 유사 MonadPlus
하며 유사한 분배 및 캐치 속성이 존재하며, 그중 적어도 하나는 만족해야합니다.
불행히도 empty <*> m = empty
법률 조차도 너무 강력한 주장입니다. 예를 들어 Backwards 에는 적용되지 않습니다 !
MonadPlus를 보면 빈 >> = f = 빈 법칙이 거의 우리에게 강요됩니다. 빈 구조는 f
어쨌든 함수를 호출하기 위해 ‘a’를 가질 수 없습니다 .
때문에, Applicative
있다 없다 의 슈퍼 클래스 Monad
및 Alternative
인 하지 의 슈퍼 클래스 MonadPlus
, 우리는 별도로 두 인스턴스를 정의하는 바람.
더군다나 Applicative
의 슈퍼 클래스였다 하더라도 어쨌든 클래스 Monad
가 필요 MonadPlus
하게 될 것입니다.
empty <*> m = empty
그것은 증명하기에 충분하지 않습니다.
empty >>= f = empty
그래서 무언가가 a MonadPlus
라고 주장하는 것은 그것이 있다고 주장하는 것보다 더 강합니다 Alternative
.
이제 규칙에 따라 MonadPlus
그리고 Alternative
해당 유형에 대한 동의한다, 그러나이 Monoid
될 수있다 완전히 다른.
예를 들어 MonadPlus
and Alternative
for Maybe
는 명백한 일을합니다.
instance MonadPlus Maybe where
mzero = Nothing
mplus (Just a) _ = Just a
mplus _ mb = mb
그러나 Monoid
인스턴스는 세미 그룹을 Monoid
. 안타깝게도 Semigroup
Haskell 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
, 이는 차례로보다 강력한 클레임이며 유형 Monoid
의 MonadPlus
및 Alternative
인스턴스는 관련되어야하지만 Monoid
완전히 다른 것일 수 있습니다 (때로는 그렇습니다).