2010-11-20 42 views
7

Come mai, che il seguente tipo di controlliCome funzionano esattamente i sinonimi di tipo?

{-# LANGUAGE RankNTypes #-} 
module Main where 

class Foo a where 


type FunFoo = (Foo a) => a -> IO() 

data Bar = Bar { 
    funFoo :: FunFoo 
} 

setFunFoo :: FunFoo -> Bar -> Bar 
setFunFoo action bar = bar {funFoo = action} 

ma quando si cambia la firma di tipo off setFunFoo a

setFunFoo :: ((Foo a) => a -> IO()) -> Bar -> Bar 

non lo fa? C'è un modo per esprimere il codice sopra senza il sinonimo di tipo FunFoo?

+3

Sei sicuro si intendeva utilizzare i tipi di rango-n? Questo è un argomento abbastanza avanzato per qualcuno che chiede come funzionano i sinonimi di tipo. –

risposta

7

è necessario aggiungere un esplicito forall in questo modo:

setFunFoo :: (forall a. (Foo a) => a -> IO()) -> Bar -> Bar 

La ragione di questo è perché si desidera che il campo di applicazione del tipo di variabile a a essere limitata al tipo del primo argomento a setFunFoo. Senza l'esplicito forall, il tipo di Dezuccherato è questo:

setFunFoo :: forall a. ((Foo a) => a -> IO()) -> Bar -> Bar