Một điều khiến nó khó hiểu là các chức năng "phổ biến" như bind
và <*>
được định hướng. Nhưng để hiểu các khái niệm trước tiên, dễ dàng hơn để xem xét các chức năng khác. Cũng đáng lưu ý rằng các đơn vị nổi bật bởi vì họ hơi vượt trội so với các khái niệm kết nối khác. Vì vậy, tôi sẽ bắt đầu với functor thay thế.
Functor cung cấp một chức năng (theo ký hiệu Haskell) fmap :: (Functor f) => (a -> b) -> f a -> f b
. Nói cách khác, bạn có một bối cảnh f
mà bạn có thể nâng một hàm vào. Như bạn có thể tưởng tượng hầu hết mọi thứ là một functor. Danh sách, Có thể, Hoặc, chức năng, I / O, bộ dữ liệu, trình phân tích cú pháp ... Mỗi đại diện cho một bối cảnh trong đó một giá trị có thể xuất hiện. Vì vậy, bạn có thể viết các hàm cực kỳ linh hoạt hoạt động trong hầu hết mọi ngữ cảnh bằng cách sử dụng fmap
hoặc biến thể nội tuyến của nó<$>
.
Những thứ khác bạn muốn làm với bối cảnh? Bạn có thể muốn kết hợp hai bối cảnh. Vì vậy, bạn có thể muốn có được một khái quát về zip :: [a] -> [b] -> [(a,b)]
ví dụ như thế này : pair :: (Monoidal f) => f a -> f b -> f (a,b)
.
Nhưng bởi vì nó thậm chí còn hữu ích hơn trong thực tế, các thư viện Haskell thay vào đó cung cấp Applicative
, đó là sự kết hợp của Functor
và Monoidal
, và cũng Unit
chỉ thêm rằng bạn thực sự có thể đặt các giá trị "bên trong" bối cảnh của mình unit
.
Bạn có thể viết các hàm cực kỳ chung chung bằng cách chỉ ra ba điều sau về bối cảnh bạn đang làm việc.
Monad
chỉ là một điều khác mà bạn có thể nêu lên trên đó. Điều tôi chưa từng đề cập trước đây là bạn đã có hai cách để kết hợp hai bối cảnh: Bạn không chỉ có pair
chúng mà còn có thể xếp chồng chúng, ví dụ bạn có thể có một danh sách các danh sách. Trong ngữ cảnh I / O, một ví dụ sẽ là một hành động I / O có thể đọc các hành động I / O khác từ một tệp, vì vậy bạn sẽ có một loại FilePath -> IO (IO a)
. Làm thế nào chúng ta có thể thoát khỏi ngăn xếp đó để có được một chức năng thực thi IO a
? Đó là nơi mà Monad
sjoin
đi vào, nó cho phép chúng ta kết hợp hai bối cảnh xếp chồng lên nhau của cùng loại. Điều tương tự cũng xảy ra với các trình phân tích cú pháp, Có thể vv Và bind
chỉ là một cách thực tế hơn để sử dụngjoin
Vì vậy, một bối cảnh đơn điệu chỉ phải cung cấp bốn thứ và nó có thể được sử dụng với hầu hết tất cả các máy móc được phát triển cho I / O, cho các trình phân tích cú pháp, cho các lỗi, v.v.