2013-05-09 8 views
5

Ecco una classe molto utile:vincoli universalmente generalizzate

class Foo f a where 
    foo :: f a 

E ti permette di fare mi ha valori di default per un sacco di tipi. In realtà, potrei anche non aver bisogno di sapere che cos'è a.

instance Foo Maybe a where 
    foo = Nothing 

ora ho un Maybe a per tutti a, e posso specializzarsi in un secondo momento.

specialize :: (forall a. f a) -> f Int 
specialize x = x 

fooMaybe :: Maybe Int 
fooMaybe = specialize foo 

Hmmm .... che fooMaybe sembra abbastanza specifico. Vediamo se posso usare un contesto per generalizzarlo:

fooAll :: (Foo f a) => f Int 
fooAll = specialize foo 

Oops! Non indovinare.

Foo.hs:18:21: 
    Could not deduce (Foo * f a1) arising from a use of `foo' 
    from the context (Foo * f a) 
     bound by the type signature for fooAll :: Foo * f a => f Int 
     at Foo.hs:17:11-28 

Quindi, la mia domanda è, come posso scrivere fooAll, la versione generalizzata di fooMaybe? O, più in generale, come è possibile generalizzare universalmente un vincolo di typeclass?

+1

Non è possibile. Bene, puoi scrivere 'fooAll' se crei un' esempio Foo f a dove foo = undefined'. Ma non è utile. Non è possibile quantificare universalmente il vincolo, non è possibile scrivere 'fooAll :: (forall a. Foo f a) => f Int'. –

risposta

7

Nessun buon modo in Haskell attuale adesso. Il pacchetto constraints fornisce un tipo che potrebbe essere do what you need, anche se recentemente ho capito come romperlo. Ancora probabilmente la tua migliore scommessa, perché se qualcuno capisce come farlo bene probabilmente verrà aggiornato

fooAll :: Forall (Foo f) => f Int 
fooAll = specialize foo_f where 
    foo_f :: forall a. f a 
    foo_f = foo \\ (inst `trans` (Sub Dict) ::() :- Foo f a)