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

, это должно быть то же самое, что и просто вызов функции >id с тем же значением функтора. Наш пример показывает, что это не относится к нашему функтору >CMaybe. Хотя он и имеет экземпляр класса >Functor, он не подчиняется данному закону функторов и, следовательно, не является функтором.

Поскольку тип >CMaybe не является функтором, хотя он и притворяется таковым, использование его в качестве функтора может привести к неисправному коду. Когда мы используем функтор, не должно иметь значения, производим ли мы сначала композицию нескольких функций, а затем с её помощью отображаем значение функтора, или же просто отображаем значение функтора последовательно с помощью каждой функции. Но при использовании типа >CMaybe это имеет значение, так как он следит, сколько раз его отобразили. Проблема!.. Если мы хотим, чтобы тип >CMaybe подчинялся законам функторов, мы должны сделать так, чтобы поле типа >Int не изменялось, когда используется функция >fmap.

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

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

Использование аппликативных функторов

В этом разделе мы рассмотрим аппликативные функторы, которые являются расширенными функторами.



До настоящего времени мы были сосредоточены на отображении функторов с помощью функций, принимающих только один параметр. Но что происходит, когда мы отображаем функтор с помощью функции, которая принимает два параметра? Давайте рассмотрим пару конкретных примеров.

Если у нас есть >Just 3, и мы выполняем выражение >fmap (*) (Just 3), что мы получим? Из реализации экземпляра типа >Maybe для класса >Functor