Недавно я пытался изучить Haskell с помощью «Learn You a Haskell» и действительно пытался понять функции в качестве Применительных.Я должен отметить, что при использовании других типов Аппликативов, таких как Списки и Возможно, я, кажется, достаточно хорошо понимаю, чтобы использовать их эффективно.
Как я склонен делать, пытаясь что-то понять, я пытался поиграть с таким количеством примеров.как я мог, и как только шаблон появляется, вещи имеют смысл.В качестве такового я попробовал несколько примеров.Прилагаются примечания к нескольким примерам, которые я попробовал вместе с диаграммой, которую я нарисовал, чтобы попытаться визуализировать происходящее.
Определение funct
не похоже на результат, но в моих тестах я использовал функцию со следующим определением:
funct :: (Num a) => a -> a -> a -> a
Внизу я попытался показать то же самое, что и на диаграммах, просто используя обычную математическую запись.
Так что все это хорошо, я могу понять шаблон, когда у меня есть какая-то функция с произвольным числом аргументов (хотя требуется 2 или более), и применить ее к функции, которая принимает один аргумент.Однако интуитивно этот шаблон не имеет для меня особого смысла.
Итак, у меня есть конкретные вопросы:
Что такое интуитивный способ понять шаблонЯ вижу, особенно если я рассматриваю Applicative как контейнер (как я вижу Maybe
и списки)?
Каков шаблон, когда функция справа от <*>
занимает большечем один аргумент (в основном я использовал функцию (+3)
или (+5)
справа)?
почему функция справа от <*> применяется ко второму аргументуфункции на левой стороне.Например, если функция с правой стороны была f()
, то funct(a,b,c)
превращается в funct (x, f(x), c)
?
Почему она работает для funct <*> (+3)
, но не для funct <*> (+)
?Более того, он работает на (\ a b -> 3) <*> (+)
. Любое объяснение, которое дает мне лучшее интуитивное понимание этой концепции, будет с благодарностью.Я читал другие объяснения, такие как в упомянутой книге, в которой функции объясняются в терминах ((->)r)
или аналогичных шаблонов, но хотя я знаю, как использовать оператор ->
) при определении функции, я не уверен, что понимаю ее вэтот контекст.
Дополнительные сведения:
Я также хочу включить фактический код, который я использовал, чтобы помочь мне сформировать диаграммы выше.
Сначала яопределил функцию, как я показал выше:
funct :: (Num a) => a -> a -> a -> a
На протяжении всего процесса я усовершенствовал функцию различными способами, чтобы понять, что происходит.
Далее я попробовал этот код:
funct a b c = 6
functMod = funct <*> (+3)
functMod 2 3
Неудивительно, что результат был 6
Так что теперь я попытался просто вернуть каждый аргумент прямо так:
funct a b c = a
functMod = funct <*> (+3)
functMod 2 3 -- returns 2
funct a b c = b
functMod = funct <*> (+3)
functMod 2 3 -- returns 5
funct a b c = c
functMod = funct <*> (+3)
functMod 2 3 -- returns 3
Из этого я смог подтвердить, что вторая диаграмма - это то, что нужноместо.Я повторил эти паттерны, чтобы наблюдать и третью диаграмму (которая повторяет те же паттерны, которые повторяются сверху).