2016-09-29 2 views
3

Cela m'a bloqué. Comment écrire une instance de Functor pour newtype Mu f = InF {outF :: f (Mu f)}Instance Functor pour (newtype Mu f = InF {outF :: f (Mu f)})

+3

Si vous faites newtype Mu f a = InF {outF :: f (Mu f a)} ', alors' l'instance Functor f => Functor (Mu f) 'est possible. C'est juste 'Free' sans le constructeur' Pure', cependant. – user2297560

+0

Vérifiez https://github.com/ekmett/recursion-schemes/pull/23 pour réfléchir à ce problème. – phadej

+0

Pour les intéressés, il s'agit d'un exercice du chapitre 16. Fonctionnaires de * Haskell Programmation des premiers principes *. –

Répondre

7

Vous ne pouvez pas. Afin de définir une instance Functor c pour certains c, c doit être du type * -> *. Donc, dans votre cas, Mu aurait dû être de ce type, ce qui signifie que son argument f doit avoir été du type *. Mais clairement ce n'est pas le cas, car vous appliquez f à autre chose (à Mu f).

Pour plus simplement, si Mu était un foncteur, vous pouvez utiliser fmap sur les valeurs de type Mu f pour tout f. Mais cela vous aurait permis de changer le paramètre de type en n'importe quel autre type, par exemple, en appliquant la fonction fmap (const (0 :: Int)) à une valeur Mu f, il faudrait retourner une valeur Mu Int. Mais vous ne pouvez pas former une telle valeur parce que le outF de cette valeur aurait eu le type Int (Mu Int) ce qui n'a pas de sens.

+0

J'ajouterais la signature de type explicite 'Mu :: (* -> *) -> *' pour souligner que ce n'est pas celui requis par 'Functor' (' * -> * 'comme mentionné ci-dessus), donc nous obtenir une erreur gentille. – chi

4

redneb donne une bonne explication des raisons pour lesquelles Mu ne peut pas être un Functor régulier mais vous pouvez mettre en œuvre une sorte d'opération de cartographie foncteur comme pour Mu comme

{-# LANGUAGE RankNTypes #-} 

newtype Mu f = InF {outF :: f (Mu f)} 

mumap :: Functor f => (forall a. f a -> g a) -> Mu f -> Mu g 
mumap f (InF m) = InF $ f $ fmap (mumap f) m 

Bien que je ne sais pas comment il serait utile être dans ton cas. :)

+1

IOW 'Mu' est un foncteur de la catégorie des constructeurs de type' * -> * '(dont les morphismes sont des transformations naturelles' forall x .f x -> g x') à la catégorie des types Haskell '*' et fonctions –

0

Une légère re-phrasé de Mu, différente de celle des user2297560, est suffisante pour admettre une instance Functor pour Mu:

-- Natural transformations 
type g ~> h = forall a. g a -> h a 

class HFunctor f where 
    ffmap :: Functor g => (a -> b) -> f g a -> f g b 
    hfmap :: (Functor g, Functor h) => (g ~> h) -> (f g ~> f h) 

newtype Mu f a = In { unIn :: f (Mu f) a } 

instance HFunctor f => Functor (Mu f) where 
    fmap f (In r) = In (ffmap f r) 

Cette formulation provient du papier de Patricia et Neil Haskell Programming with Nested Types: A Principled Approach.