Ваш аккаунт, конечно, прав. Возможно, причина, по которой у нас возникают трудности с такими экземплярами, заключается в том, что мы действительно определяем бесконечно много экземпляров функторов одновременно - по одному для каждого возможного типа Left
. Но экземпляр Functor - это систематический способ работы с бесконечным числом типов в системе. Таким образом, мы определяем бесконечно много способов систематической работы с бесконечно большим количеством типов в системе. Экземпляр включает в себя общность двумя способами.
Если взять это поэтапно, возможно, это не так странно. Первый из этих типов - это длинная версия Maybe
, использующая тип устройства ()
и его единственное допустимое значение ()
:
data MightBe b = Nope () | Yep b
data UnlessError b = Bad String | Good b
data ElseInt b = Else Int | Value b
Здесь мы можем устать и сделать абстракцию:
data Unless a b = Mere a | Genuine b
Теперь мы создаем наши экземпляры Functor без проблем, первые выглядят очень похоже на экземпляр для Maybe
:
instance Functor MightBe where
fmap f (Nope ()) = Nope () -- compare with Nothing
fmap f (Yep x) = Yep (f x) -- compare with Just (f x)
instance Functor UnlessError where
fmap f (Bad str) = Bad str -- a more informative Nothing
fmap f (Good x) = Good (f x)
instance Functor ElseInt where
fmap f (Else n) = Else n
fmap f (Value b) = Value (f b)
Но, опять же, зачем, давайте сделаем абстракцию:
instance Functor (Unless a) where
fmap f (Mere a) = Mere a
fmap f (Genuine x) = Genuine (f x)
Термины Mere a
не затрагиваются, поскольку значения ()
, String
и Int
не затрагиваются.