Sự khác biệt giữa kính xếp chữ MonadPlus, Alternative và Monoid?


83

Thư viện chuẩn Haskell typeclasses MonadPlus, AlternativeMonoidmỗi thứ cung cấp hai phương thức có ngữ nghĩa về cơ bản giống nhau:

  • Một giá trị rỗng: mzero, empty, hoặc mempty.
  • Một nhà điều hành a -> a -> amà gia nhập giá trị trong typeclass với nhau: mplus, <|>, hoặc mappend.

Cả ba đều chỉ rõ những luật này mà các trường hợp phải tuân thủ:

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

Do đó, có vẻ như ba kính xếp chữ đều cung cấp các phương pháp giống nhau .

( Alternativecũng cung cấp somemany, nhưng các định nghĩa mặc định của chúng thường là đủ, và vì vậy chúng không quá quan trọng về mặt câu hỏi này.)

Vì vậy, truy vấn của tôi là: tại sao lại có ba lớp cực kỳ giống nhau này? Có sự khác biệt thực sự nào giữa chúng, ngoài những ràng buộc khác nhau về lớp cha không?


Đó là một câu hỏi hay. Đặc biệt, ApplicativeMonadPlusdường như hoàn toàn giống nhau (ràng buộc siêu lớp modulo).
Peter

1
Ngoài ra còn có ArrowZeroArrowPluscho các mũi tên. Đặt cược của tôi: để làm cho các chữ ký kiểu sạch hơn (điều này làm cho các ràng buộc siêu lớp khác nhau trở thành sự khác biệt thực sự).
Cat Plus Plus

2
@CatPlusPlus: tốt, ArrowZeroArrowPluscó loại * -> * -> *, có nghĩa là bạn có thể chuyển chúng cho loại mũi tên một lần cho một chức năng cần sử dụng chúng cho vô số loại, để sử dụng một, Monoidbạn phải yêu cầu một phiên bản Monoidcho từng loại cụ thể và bạn không có gì đảm bảo rằng chúng được xử lý theo cách tương tự, các trường hợp có thể không liên quan!
Edward KMETT

Câu trả lời:


120

MonadPlusMonoidphục vụ các mục đích khác nhau.

A Monoidđược tham số hóa trên một kiểu loại *.

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

và do đó, nó có thể được khởi tạo cho hầu hết mọi kiểu mà có toán tử hiển nhiên là liên kết và có đơn vị.

Tuy nhiên, MonadPluskhông chỉ chỉ định rằng bạn có cấu trúc đơn nguyên, mà cấu trúc đó còn liên quan đến cách Monadhoạt động cấu trúc đó không quan tâm đến giá trị chứa trong đơn nguyên, điều này (một phần) được chỉ ra bởi thực tế rằng MonadPluscó một đối số của loại hình * -> *.

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

Ngoài các luật đơn nguyên, chúng ta có hai bộ luật tiềm năng mà chúng ta có thể áp dụng MonadPlus. Đáng buồn thay, cộng đồng không đồng ý về những gì họ nên là.

Ít nhất chúng ta biết

mzero >>= k = mzero

nhưng có hai phần mở rộng cạnh tranh khác, luật phân phối bên trái (sic)

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

và luật bắt trái

mplus (return a) b = return a

Vì vậy, bất kỳ trường hợp nào của MonadPlusphải đáp ứng một hoặc cả hai luật bổ sung này.

Vậy thì Alternativesao?

Applicativeđược định nghĩa sau Monad, và về mặt logic thuộc về một lớp cha của Monad, nhưng phần lớn là do những áp lực khác nhau đối với các nhà thiết kế trong Haskell 98, thậm chí Functorkhông phải là lớp cha Monadcho đến năm 2015. Giờ đây, cuối cùng chúng ta đã có Applicativedưới dạng lớp cha của MonadGHC (nếu không chưa theo tiêu chuẩn ngôn ngữ.)

Hiệu quả, AlternativeApplicativenhững gì MonadPlusphải làm Monad.

Đối với những điều này, chúng tôi sẽ nhận được

empty <*> m = empty

tương tự như những gì chúng tôi có MonadPlusvà tồn tại các thuộc tính phân phối và bắt tương tự, ít nhất một trong số đó bạn nên đáp ứng.

Thật không may, ngay cả empty <*> m = emptyluật pháp cũng là một yêu sách quá mạnh. Nó không giữ cho BackwardVí dụ, !

Khi chúng ta nhìn vào MonadPlus, định luật rỗng >> = f = rỗng gần như bị ép buộc đối với chúng ta. Cấu trúc trống không thể có bất kỳ 'a's nào trong đó để gọi hàm fbằng mọi cách.

Tuy nhiên, vì Applicativekhông một lớp cha của MonadAlternativekhông một lớp cha của MonadPlus, chúng tôi gió lên xác định cả hai trường hợp riêng biệt.

Hơn nữa, ngay cả khi Applicativelà một lớp cha Monad, bạn vẫn cần đến MonadPluslớp đó, bởi vì ngay cả khi chúng ta tuân theo

empty <*> m = empty

điều đó không đủ nghiêm ngặt để chứng minh rằng

empty >>= f = empty

Vì vậy, tuyên bố rằng một cái gì đó là a MonadPlusmạnh hơn tuyên bố nó là Alternative.

Bây giờ, theo quy ước, MonadPlusAlternativeđối với một loại nhất định phải đồng ý, nhưng Monoidcó thể hoàn toàn khác.

Ví dụ MonadPlusAlternativecho Maybelàm điều rõ ràng:

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

nhưng Monoidtrường hợp nâng một nhóm bán thành một Monoid. Đáng buồn là vì không tồn tại một Semigrouplớp vào thời điểm đó trong Haskell 98, nó làm như vậy bằng Monoidcách sử dụng a , nhưng không sử dụng đơn vị của nó. ಠ_ಠ

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 là một xác nhận quyền sở hữu mạnh hơn Alternative, ngược lại là một xác nhận quyền sở hữu mạnh hơn Monoid, và trong khi các MonadPlusvà các Alternativetrường hợp của một loại phải có liên quan với nhau, thì Monoidcó thể (và đôi khi là) một cái gì đó hoàn toàn khác.


2
Câu trả lời xuất sắc, tuy nhiên định nghĩa cuối cùng có vẻ sai, nó không thỏa mãn mempty `mappend` x ≡ x.
Vitus

2
Câu trả lời chính xác. Có ai biết về một loại (thường được sử dụng) có khác nhau MonadPlusAlternativetriển khai không?
Peter

7
@EdwardKmett: Câu trả lời này dường như ngụ ý rằng có thể có Monadmột Alternativenhưng không phải là a MonadPlus. Tôi đã đặt một câu hỏi về việc tìm một ví dụ cụ thể về điều này; nếu bạn biết về một cái, tôi rất muốn xem nó.
Antal Spector-Zabusky,

2
Bạn có thể giải thích luật bắt trái cho monadplus? Nó dường như bị vi phạm bởi []; [] có nên thực sự bỏ qua đối số thứ hai của nó nếu đối số thứ nhất của nó không trống không?
ben w

4
@benw phân phối trái được cho là luật hợp lý hơn, nhưng nó không đúng trong một số trường hợp. bắt trái là một luật thay thế mà những trường hợp khác có xu hướng ủng hộ, nhưng lại không được hầu hết các trường hợp khác ủng hộ. Do đó, chúng ta thực sự có 2 bộ luật phần lớn không liên quan được thực hiện bởi các trường hợp khác nhau, vì vậy MonadPlusthực sự là hai lớp được ngụy trang thành một vì hầu hết mọi người không quan tâm.
Edward KMETT
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.