Почему Ничего >> Только 3 - Ничто в Хаскеле?
Подпись >>
Функция в Haskell заключается в следующем:
(>>) :: m a -> m b -> m b
И реализация по умолчанию:
x >> y = x >>= \_ -> y
Под этим я понимаю, что >>
Функция всегда возвращает свой правый параметр независимо от значения левого. Лямбда даже не заботится о значении левого параметра (x). Тогда почему Nothing >> Just 3
равно Nothing
? Разве это не должно просто вернуться Just 3
, так как это значение аргумента справа?
Я знаю что нибудь Just
значение, вернется Nothing
когда связано с Nothing
, но в этом случае Nothing
даже не захвачен лямбдой. Что мне не хватает?
Бонусный вопрос, >>=
называется связать. Что такое >>
называется?
Благодарю.
5 ответов
Потому что привязка даже не заботится о значении лямбды!
Just x >>= f = f x
Nothing >>= _ = Nothing
Обратите внимание (Nothing >>=)
не оценивает свой второй аргумент.
Чтобы действительно понять, что (>>)
В этом случае вы должны посмотреть на определение (>>=)
за Maybe
:
(Just x) >>= k = k x
Nothing >>= _ = Nothing
Nothing >>= k
оценивает Nothing
независимо от того, что k
функция есть. В конкретном случае (>>)
, k
просто бывает \_ -> y
,
Под этим я понимаю, что функция >> всегда возвращает свой правый параметр независимо от значения левого
Это источник вашего замешательства!
m >>= f
Запускает f
для значений он "находит внутри" m
, "объединение" результатов (где то, что означает "находить внутри" монадическое значение и что означает "объединять", зависит от монады).
m >> n
должен быть эквивалентен m >>= \_ -> n
, Так что для каждого значения он находит внутри m
, это вызовет \_ -> n
в теме. Но Nothing
в Maybe
Монада не имеет никаких значений "внутри". Так \_ -> n
никогда не может быть призван на что-либо, чтобы проигнорировать это и вернуться n
! Так Nothing >>= \_ -> n
должен вернуть то, что не зависит от n
, так как он не имеет возможности вызвать функцию для получения n
, Также в этом контексте нет никаких значений обернутого типа, поэтому единственная доступная опция - это просто Nothing
,
Так что вместо вашей интуиции для понимания >>
поскольку он игнорирует левое и возвращает то, что справа, лучше думать, что он берет "монадическую структуру" того, что слева, и связывает ее с монадическим значением справа. "Монадическая структура" - это волнообразный термин для "всего, что определяет монадическое значение, кроме значений внутри него".
listA >> listB
делает то же самое, независимо от конкретных значений в listA
, но это имеет значение, сколько элементов в нем. ioA >> ioB
делает то же самое, независимо от того, какое значение производится путем выполнения ioA
, но это имеет значение, побочные эффекты были сделаны, чтобы произвести это. stateA >> stateB
игнорирует значение, произведенное stateA
, но отправляет текущее состояние stateB
, А также maybeA >> maybeB
делает то же самое, независимо от конкретного значения внутри maybeA
, но это имеет значение, есть ли ценность или нет. Обратите внимание, что регистр ведет себя очень похоже на Maybe
; если listA
тогда пусто listA >> listB
тоже должен быть пустым.
Что касается вашего бонусного вопроса, когда я читаю код для себя (в своей голове), я склонен произносить оба >>=
а также >>
как "связать"; когда я смотрю на код и произношу его, достаточно невербального понимания контекста, чтобы эта двусмысленность не имела значения. Я на самом деле не знаю, что бы я сказал, чтобы поговорить с кем-то о >>=
а также >>
; может быть "связать" и "забыть связать"?
Я думаю, что есть два способа объяснить выбор.
вы апеллируете к тому факту, что Maybe, в отличие от IO, например, не имеет побочных эффектов. В противном случае отказ от второго аргумента не имеет смысла. С этой точки зрения, это выглядит как произвольный выбор с логической точки зрения, хотя, безусловно, он более эффективен, если не является неожиданным.
Вы заставляете Ничто не представлять ошибку. Тогда ошибка в первом аргументе избавит от необходимости оценивать второй аргумент. Похоже, это обоснование, выбранное авторами:
http://hackage.haskell.org/package/base-4.7.0.0/docs/src/Data-Maybe.html
-- The 'Maybe' type is also a monad. It is a simple kind of error
-- monad, where all errors are represented by 'Nothing'.
Есть несколько вещей, которые я хотел бы добавить к другим хорошим ответам.
Причина
Nothing >>= f
должен бытьNothing
потому что невозможно проверить,f
фактически использует его аргумент (по крайней мере, без ужасных небезопасных хаков).x >> y = x >>= \_ -> y
это не просто реализация по умолчанию. Определение>>
должен всегда давать тот же результат, что и этот. Его можно перегрузить только потому, что иногда его можно реализовать более эффективно.