2012-08-30 15 views
10

¿Hay alguna forma de tener instancias de tipo predeterminadas definidas en términos de la otra? Estoy intentando conseguir algo como esto de trabajo:Instancias de tipo predeterminado que se refieren entre sí

{-# LANGUAGE DataKinds, KindSignatures #-} 
{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE UndecidableInstances #-} 
data Tag = A | B | C 

class Foo (a :: *) where 
    type Bar a (b :: Tag) 

    type Bar a A =() 
    type Bar a B = Bar a A 
    type Bar a C = Bar a A 

instance Foo Int where 
    type Bar Int A = Bool 

test :: Bar Int B 
test = True 

pero esto no funciona:

Couldn't match type `Bar Int 'B' with `Bool' 
In the expression: True 
In an equation for `test': test = True 

Tenga en cuenta que esto no funciona bien:

test :: Bar Int B 
test =() 

Respuesta

3

Sí, las instancias de tipo predeterminado se pueden definir en términos de cada uno (como puede ver en su propio ejemplo):

instance Foo Int where 
-- So the default recursive definition will be used instead 
-- type Bar Int A = Bool 

test :: Bar Int B 
test =() 

Sin embargo, cuando se redefine asociado sinónimo de tipo en la definición de instancia para Int que reemplace predeterminado Defintion de 3 líneas de Bar (y no sólo el type Bar a A =()) con una línea type Bar Int A = Bool lo que significa Bar Int B y Bar Int C ya no se definen.

así que supongo que una de las maneras de utilizar los valores por defecto recursivas la manera que quería es redefinir sinónimos específicos lugar (aunque es bastante detallado):

class Foo (a :: *) where 
    type Bar a (b :: Tag) 
    type Bar a A = BarA a 
    type Bar a B = BarB a 

    type BarA a 
    type BarA a =() 

    type BarB a 
    type BarB a = Bar a A 

-- This now works 
instance Foo Int where 
    type BarA Int = Bool 

test :: Bar Int B 
test = True 

que pueden caer de nuevo a defectos:

-- As well as this one 
instance Foo Int where 
-- type BarA Int = Bool 

test :: Bar Int B 
test =() 
Cuestiones relacionadas