2013-04-17 12 views
10

Ich versuche herauszufinden, ob es möglich ist (und wie) Klasseninstanzen für Multi-Parameter-Typ Synonyme zu definieren.Multi-Parameter Typ Synonym Instanzen

Zum Beispiel:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} 

type F a b = a -> b 
data DF a b = DF (a -> b) 

class C c a b where 
    doc :: c a b -> a -> b 

Es funktioniert für eine Multi-param Typ-Instanz:

instance C DF a b where 
    doc (DF f) x = f x 

Aber es funktioniert nicht für Synonyme Typ:

-- ERROR: 
-- 
-- Type synonym `F' should have 2 arguments, but has been given none 
-- In the instance declaration for `C F a b' 
-- 
instance C F a b where 
    doc f x = f x 

Ist es möglich, eine Typklasseninstanz für F zu definieren?

Antwort

14

Es ist nicht möglich, wie geschrieben. Typ Synonyme müssen im Allgemeinen vollständig angewendet werden, um sie zu verwenden, insbesondere as a type class parameter.

Beachten Sie, dass, wenn Sie den Typ Synonym genug reduzieren können, eine Instanz möglich ist; es ist das Synonym, das vollständig angewendet werden muss, nicht der Typ, auf den es sich bezieht. So würde diese Arbeit:

type F = (->) 

instance C F a b where 
    doc f x = f x 

Es gibt a LiberalTypeSynonyms extension that relaxes some of the rules über Typ Synonyme erweitert, aber es hilft hier nicht - es können nur tun Sie Dinge wie ein den teilweise aufgebrachten Typ Synonym als Typparameter eines anderen Typs Synonym. Alles muss noch vollständig erweitert werden, um es anderweitig zu verwenden.

einen Grund zu sehen, warum diese Einschränkung notwendig ist, sollten Sie das folgende Typen Synonym:

type Flip f a b = f b a 

Und das folgende Beispiel:

instance Functor (Flip Either a) where 
    fmap _ (Right x) = Right x 
    fmap f (Left x) = Left (f x) 

Daran erinnern, dass Functor (Either a) auch eine Instanz gibt es, die das gleiche tut Ding, außer gespiegelt. Beide sind sinnvolle Functor Instanzen.

Denken Sie daran, dass im Gegensatz zu newtype Typ Synonyme gelten als die Art, auf die sie sich beziehen, was sollte der Wert des Ausdrucks fmap not (Right True :: Either Bool Bool) sein?

3

Typensynonyme müssen vollständig angewendet werden, damit eine Instanz für sie definiert werden kann. Die Art von F ist nicht * -> * -> *, wie man erwarten könnte, sondern stattdessen ungültig, bis zwei weitere Typargumente geliefert werden. Versuchen Sie

type F = (->) 

stattdessen.

Verwandte Themen