2017-02-05 4 views
1

Je vais par these 'intermédiaires' exercices Haskell, je l'ai fait les cas suivants:Opérateur flèche dans les déclarations d'instance de foncteur?

class Fluffy f where 
    furry :: (a -> b) -> f a -> f b 

instance Fluffy [] where 
    furry f [] = [] 

instance Fluffy Maybe where 
    furry f (Just e) = Just (f e) 
    furry f (Nothing) = Nothing 

Cependant, la troisième syntaxe question m'a déconcerté:

instance Fluffy ((->) t) where 
    ... 

J'ai lu sur l'opérateur de flèche et également lire la réponse à this qui explique le rôle de (->) dans une instance de Monad. Cependant, je ne comprends pas très bien comment fonctionne (->) dans le contexte de Functors?

Répondre

9

Nous avons:

class Fluffy f where 
    furry :: (a -> b) -> f a -> f b 

Nous voulons définir:

instance Fluffy ((->) t) where 
    furry = ... 

Cela signifie que dans le cas ci-dessus furry devrait avoir le type (a -> b) -> f a -> f bf est ((->) t), autrement dit:

furry :: (a -> b) -> ((->) t) a -> ((->) t) b 

Tout comme ((+) 2) 3 est le même que 2 + 3, ((->) X) Y est le même que X -> Y (il est l'application de l'opérateur cari et cela fonctionne même au niveau du type):

furry :: (a -> b) -> (t -> a) -> (t -> b) 

On peut lire la signature ci-dessus comme "donné une fonction de a à b et une fonction de t à a, retourner une fonction de t à b ".

Maintenant, il suffit de l'implémenter. :-)

2

Nous définissons l'instance Functor en tant que tel:

instance Functor ((->) a) where 
    fmap f g = \a -> f (g a) 
    -- Pointfree definition: fmap = (.) 

C'est-à-dire le foncteur (->) est comparable à un conteneur qui ne peut être « ouvert » en obtenant une valeur de type a et "ouvrir" le conteneur avec. Tout fmap est juste en train de changer la valeur après que nous 'ouvrons' le conteneur. C'est à dire: fonctions de composition.

C'est un peu comme le foncteur Maybe en ce sens que je peux appliquer une fonction à la valeur si elle existe, mais pour le foncteur (->) je le fais avant de savoir de quoi il s'agit.

Mais rappelez-vous que tous les monades sont foncteurs, puisque nous pourrions définir fmap comme si:

fmap f m = m >>= (\a -> return (f a)) 

Donc, si vous comprenez ce que cela ferait dans le cas Monad il devrait être clair ce qu'il fait dans le Functor exemple.