10

デフォルトタイプのインスタンスを相互に定義する方法はありますか?私はこのようなものを機能させようとしています:

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

しかし、これは機能しません:

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

これも機能しないことに注意してください。

test :: Bar Int B
test = ()
4

1 に答える 1

3

はい、デフォルトのタイプのインスタンスは、相互に定義できます(独自の例からわかるように)。

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

test :: Bar Int B
test = ()

ただし、インスタンス定義で関連する型の同義語を再定義すると、 (だけでなく)のデフォルトの3行定義全体が、定義されなくなったことを意味する1行にInt置き換えられます。Bartype Bar a A = ()type Bar Int A = BoolBar Int BBar Int C

したがって、再帰的なデフォルトを意図した方法で使用する方法の1つは、代わりに特定の同義語を再定義することだと思います(かなり冗長ですが)。

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

これはデフォルトにフォールバックできます:

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

test :: Bar Int B
test = ()
于 2012-08-31T05:38:45.523 に答える