Изучай Haskell во имя добра! (Липовача) - страница 187

…, мы можем написать >fmap>f>x><*>>y><*> … Вот почему модуль >Control.Applicative экспортирует оператор, названный ><$>, который является просто синонимом функции >fmap в виде инфиксного оператора. Вот как он определён:

>(<$>) :: (Functor f) => (a –> b) –> f a –> f b

>f <$> x = fmap f x

ПРИМЕЧАНИЕ. Вспомните, что переменные типов не зависят от имён параметров или имён других значений. Здесь идентификатор >f в сигнатуре функции является переменной типа с ограничением класса, которое говорит, что любой конструктор типа, который заменяет >f, должен иметь экземпляр класса >Functor. Идентификатор >f в теле функции обозначает функцию, с помощью которой мы отображаем значение >x. Тот факт, что мы использовали >f для представления обеих вещей, не означает, что они представляют одну и ту же вещь.

При использовании оператора ><$> аппликативный стиль проявляет себя во всей красе, потому что теперь, если мы хотим применить функцию >f к трем аппликативным значениям, можно просто написать >f <$> x <*> y <*> z. Если бы параметры были обычными значениями, мы бы написали >f x y z.

Давайте подробнее рассмотрим, как это работает. Предположим, что мы хотим соединить значения >Just "johntra" и >Just "volta" в одну строку, находящуюся внутри функтора >Maybe. Сделать это вполне в наших силах!

>ghci> (++) <$> Just "johntra" <*>

>Just "volta" Just "johntravolta"

Прежде чем мы увидим, что происходит, сравните предыдущую строку со следующей:

>ghci> (++) "johntra" "volta"

>"johntravolta"

Чтобы использовать обычную функцию с аппликативным функтором, просто разбросайте вокруг несколько ><$> и ><*>, и функция будет работать с аппликативными значениями и возвращать аппликативное значение. Ну не здорово ли?

Возвратимся к нашему выражению >(++) <$> Just "джонтра" <*> Just "волта": сначала оператор >(++), который имеет тип >(++) :: [a] – > [a] –> [a], отображает значение >Just "джонтра". Это даёт в результате такое же значение, как >Just ("джонтра"++), имеющее тип >Maybe ([Char] –> [Char]). Заметьте, как первый параметр оператора >(++) был «съеден» и идентификатор >a превратился в тип >[Char]! А теперь выполняется выражение >Just ("джонтра"++) <*> Just "волта", которое извлекает функцию из >Just и отображает с её помощью значение >Just "волта", что в результате даёт новое значение – >Just "джонтраволта". Если бы одним из двух значений было значение >Nothing, результатом также было бы >Nothing.

Списки

Списки (на самом деле конструктор типа списка, >[]) являются аппликативными функторами. Вот так сюрприз! Вот как >[] является экземпляром класса >Applicative