2012-08-30 12 views
10

Czy istnieje sposób na domyślne zdefiniowanie instancji typu względem siebie? Próbuję coś jak to Działanie:Domyślne instancje typu odnoszące się do siebie

{-# 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 

ale to nie działa:

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

Należy pamiętać, że to nie działa albo:

test :: Bar Int B 
test =() 

Odpowiedz

3

Tak, Domyślne instancje typów można definiować wzajemnie (jak widać na przykładzie):

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

test :: Bar Int B 
test =() 

Jednak kiedy przedefiniować typ synonim związany w swojej definicji instancji dla Int zastąpić całą domyślny 3-liniowy Definition of Bar (a nie tylko type Bar a A =()) z jednej linii type Bar Int A = Bool co oznacza Bar Int B i Bar Int C nie są już zdefiniowane.

Sądzę więc, że jednym ze sposobów, aby używać rekurencyjnych Ustawienia domyślne sposób przeznaczony jest do ponownego konkretnych synonimy zamiast (choć jest to raczej gadatliwy):

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 

Który może spaść z powrotem do ustawień:

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

test :: Bar Int B 
test =() 
Powiązane problemy