Nel mio tempo libero sto imparando Haskell, quindi questa è una domanda per principianti.Capire come sia un'istanza di Functor
Nelle mie letture mi sono imbattuto in un esempio che illustra come Either a
è fatto un'istanza di Functor
:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
Ora, io sto cercando di capire il motivo per cui le mappe di attuazione nel caso di un costruttore Right
valore, ma non nel caso di un Left
?
Qui è la mia comprensione:
Innanzitutto vorrei riscrivere l'istanza di cui sopra come
instance Functor (Either a) where
fmap g (Right x) = Right (g x)
fmap g (Left x) = Left x
Ora:
So che
fmap :: (c -> d) -> f c -> f d
Se sostituiamo
f
conEither a
otteniamofmap :: (c -> d) -> Either a c -> Either a d
il tipo di
Right (g x)
èEither a (g x)
, e il tipo dig x
èd
, quindi abbiamo che il tipo diRight (g x)
èEither a d
, che è quello che ci aspettiamo dafmap
(vedi 2. sopra)ora, se guardiamo
Left (g x)
possiamo utilizzare lo stesso ragionamento per dire che il suo tipo èEither (g x) b
, cioèEither d b
, che non è quello che ci aspettiamo dafmap
(vedi 2. sopra): ild
dovrebbe essere il secondo parametro non il primo! Quindi non possiamo mappare suLeft
.
Il mio ragionamento è corretto?
O forse è più ovviamente un Bifunctor di un Functor - un Bifunctor ha un funzionamento bimap - bimap :: (a -> m) -> (b -> n) -> fab -> fm n. Questo ti dà la mappatura su entrambi i casi Left e Right. La libreria standard di Haskell non ha una classe Bifunctor, questo perché ci sono molti meno Bifunctor di Functors "in the wild" sebbene sia utile per Either e pair (a, b). –
In 3, si usa (g x) come parte di un tipo, ma è un valore. Sembra che tu intendessi scrivere 'typof (g x)' lì, e non '(g x)' stesso. – Peaker
@stephen tetley: è interessante! Grazie – MarcoS