Является ли (fmap f) тем же, что и (f.), Если f является функцией типа a-> b? - PullRequest
7 голосов
/ 08 апреля 2019

Я пытаюсь реализовать экземпляр Functor

data ComplicatedA a b
    = Con1 a b
    | Con2 [Maybe (a -> b)]

Для Con2 мой мыслительный процесс состоял в том, что fmap должен быть чем-то вроде

fmap f (Con2 xs) = Con2 (map f' xs)

тогда мне нужно иметь функцию списка карт f ', как

Maybe (a -> x) -> Maybe (a -> y)

Поскольку Maybe является Функтором, я могу написать f 'как

fmap ((a->x) -> (a->y))

Чтобы получить ((a->x) -> (a->y)), я подумал, что могу просто сделать fmap (x->y), что совпадает с (fmap f)

Так что мой sulotion был

instance Functor (ComplicatedA a) where
    fmap f (Con1 x y) = Con1 x (f y)
    fmap f (Con2 xs) = Con2 (map (fmap (fmap f)) xs)

Однако реальное решение использует (f .) вместо (fmap f) для получения ((a->x) -> (a->y)) из x -> y, и это выглядит так

instance Functor (ComplicatedA a) where
    fmap f (Con1 a b) = Con1 a (f b)
    fmap f (Con2 l) = Con2 (map (fmap (f .)) l)

Мне просто было интересно, в чем проблема с моим мыслительным процессом и решением. Является ли (fmap f) таким же, как (f.), Если f является функцией типа a-> b?

Заранее спасибо.

1 Ответ

6 голосов
/ 08 апреля 2019

Решения действительно эквивалентны.fmap для функтора функции / считывателя равно (.):

instance Functor ((->) r) where
    fmap = (.)

((->) r - это конструктор типа функции, используемый с синтаксисом префикса - (->) r a - этотак же, как r -> a.)

Интуиция такова, что, как вы заметили, (.) :: (x -> y) -> (a -> x) -> (a -> y) использует функцию x -> y для изменения результатов функции a -> x.

...