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

Конечно же, это ненаучный и неточный способ проверять скорость ваших программ. Однако мы могли видеть, что в этом случае использование разностных списков начинает выдавать результаты незамедлительно, тогда как использование обычных занимает нескончаемо долгое время.

Ну, теперь в вашей голове наверняка засела песня «Final Countdown» группы Europe. Балдейте!

Монада Reader? Тьфу, опять эти шуточки!

В главе 11 вы видели, что тип функции >(–>) r является экземпляром класса >Functor. Отображение функции >g с помощью функции >f создаёт функцию, которая принимает то же, что и >g, применяет к этому >g, а затем применяет к результату >f. В общем, мы создаём новую функцию, которая похожа на >g, только перед возвращением своего результата также применяет к этому результату >f. Вот пример:

>ghci> let f = (*5)

>ghci> let g = (+3)

>ghci> (fmap f g) 8

>55



Вы также видели, что функции являются аппликативными функторами. Они позволяют нам оперировать окончательными результатами функций так, как если бы у нас уже были их результаты. И снова пример:

>ghci> let f = (+) <$> (*2) <*> (+10)

>ghci> f 3

>19

Выражение >(+) <$> (*2) <*> (+10) создаёт функцию, которая принимает число, передаёт это число функциям >(*2) и >(+10), а затем складывает результаты. К примеру, если мы применим эту функцию к >3, она применит к >3 и >(*2), и >(+10), возвращая >6 и >13. Затем она вызовет операцию >(+) со значениями >6 и >13, и результатом станет >19.

Функции в качестве монад

Тип функции >(–>) r является не только функтором и аппликативным функтором, но также и монадой. Как и другие монадические значения, которые вы встречали до сих пор, функцию можно рассматривать как значение с контекстом. Контекстом для функции является то, что это значение ещё не представлено и нам необходимо применить эту функцию к чему-либо, чтобы получить её результат.

Поскольку вы уже знакомы с тем, как функции работают в качестве функторов и аппликативных функторов, давайте прямо сейчас взглянем, как выглядит их экземпляр для класса >Monad. Он расположен в модуле >Control.Monad.Instances и похож на нечто подобное:

>instance Monad ((–>) r) where

>   return x = \_ –> x

>   h >>= f = \w –> f (h w) w

Вы видели, как функция >pure реализована для функций, а функция >return – в значительной степени то же самое, что и >pure. Она принимает значение и помещает его в минимальный контекст, который всегда содержит это значение в качестве своего результата. И единственный способ создать функцию, которая всегда возвращает определённое значение в качестве своего результата, – это заставить её совсем игнорировать свой параметр.