Некоторое время назад я писал об этом: http://gabrielsw.blogspot.com/2011/08/functors-applicative-functors-and.html (хотя я не эксперт)
Первое, что нужно понять, это тип 'T [X]': это своего рода«контекст» (полезен для кодирования вещей в типах, и с их помощью вы «составляете» их). Но посмотрите другие ответы:)
Хорошо, теперь у вас есть свои типы внутри контекста, скажем, M [A] («Внутри» M), и у вас есть простая функция f: A => B ... вы не можете просто пойти дальше и применить ее, потому что функция ожидает A, и у вас есть M [A].Вам нужен какой-то способ «распаковать» содержимое M, применить функцию и «упаковать» ее снова.Если вы обладаете «глубокими» знаниями о внутренностях М, вы можете сделать это, если вы обобщите это в качестве черты, и в итоге получите
trait Functor[T[_]]{
def fmap[A,B](f:A=>B)(ta:T[A]):T[B]
}
И это именно то, чем является функтор.Он превращает T [A] в T [B], применяя функцию f.
Монада - это мифическое существо с неуловимым пониманием и множеством метафор, но я понял, что довольно легко понять, как только вы получитеаппликативный функтор:
Функтор позволяет нам применять функции к вещам в контексте.Но что, если функции, которые мы хотим применить, уже находятся в контексте?(И довольно легко закончить в этой ситуации, если у вас есть функции, которые принимают более одного параметра).
Теперь нам нужно что-то вроде Functor, но он также принимает функции уже в контексте и применяет их к элементам вконтекст.И это то, что аппликативный функтор.Вот подпись:
trait Applicative[T[_]] extends Functor[T]{
def pure[A](a:A):T[A]
def <*>[A,B](tf:T[A=>B])(ta:T[A]):T[B]
}
Пока все хорошо.Теперь монады: что если теперь у вас есть функция, которая помещает вещи в контекст?Его подпись будет g: X => M [X] ... вы не можете использовать функтор, потому что он ожидает X => Y, поэтому мы закончим с M [M [X]], вы не можете использоватьаппликативный функтор, потому что ожидает функцию уже в контексте M [X => Y].
Поэтому мы используем монаду, которая принимает функцию X => M [X] и что-то уже в контексте M [A] и применяет функцию к тому, что находится внутри контекста, упаковывая результат только в один контекст.Подпись:
trait Monad[M[_]] extends Applicative[M]{
def >>=[A,B](ma:M[A])(f:A=>M[B]):M[B]
}
Это может быть довольно абстрактно, но если вы подумаете о том, как работать с «Option», он покажет вам, как составлять функции X => Option [X]
РЕДАКТИРОВАТЬ: Забыли важную вещь, чтобы связать его: символ >> = называется bind и flatMap в Scala.(Также, как примечание, есть некоторые законы, которые функторы, аппликативы и монады должны соблюдать для правильной работы).