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