<$>
(aka fmap
) jest członkiem klasy funktora tak:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Więc cokolwiek f to musi być sparametryzowanego typu z jednego typu argumentu. Listy są jednym z takich typów, jeśli zapisano w ich prefiksie []
([] a
jest taki sam jak [a]
). Więc instancja dla list jest:
instance Functor [] where
-- fmap :: (a -> b) -> [] a -> [] b
fmap = map
Pary mogą być również napisany w formie przedrostka: (,) a b
jest taka sama jak (a, b)
. Zastanówmy się więc, co robimy, jeśli chcemy mieć instancję Functor zawierającą pary. Możemy nie można zadeklarować instance Functor (,)
, ponieważ konstruktor para (,)
ma dwa rodzaje - i mogą być różne typy! Co możemy zrobić, to zadeklarować instancję dla (,) a
- to typ, który potrzebuje tylko jednego typu więcej:
instance Functor ((,) a) where
-- fmap :: (b -> c) -> (,) a b -> (,) a c
fmap f (x, y) = (x, f y)
Mam nadzieję, że widać, że definicja FMapy jest tylko jeden sensowny możemy dać. Odpowiedź na pytanie, dlaczego instancja funktora działa na drugim elemencie pary, polega na tym, że typ drugiego elementu pojawia się na końcu! Nie możemy łatwo zadeklarować instancji funktora, która działa na pierwszym elemencie w parze. Nawiasem mówiąc, to generalizuje się na większe krotki, np. czteroosobowy (,,,) a b c d
(aka (a, b, c, d)
) może mieć również wystąpienie Functor
na ostatniej pozycji:
instance Functor ((,,,) a b c) where
-- fmap :: (d -> e) -> (,,,) a b c d -> (,,,) a b c e
fmap f (p, q, r, s) = (p, q, r, f s)
nadzieję, że pomoże to wyjaśnić wszystko!
To pytanie jest związane: http://stackoverflow.com/questions/3155469/help-haskell-functors-sink-in/3164774#3164774 –