有没有办法根据彼此定义默认类型实例?我试图让这样的工作:
{-# 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 = ()
最佳答案
是的,默认类型实例可以相互定义(从您自己的示例中可以看出):
instance Foo Int where
-- So the default recursive definition will be used instead
-- type Bar Int A = Bool
test :: Bar Int B
test = ()
但是,当您在实例定义中为
Int
重新定义关联类型同义词时你替换 整个 Bar
的默认 3 行定义(而不仅仅是 type Bar a A = ()
)只有一行 type Bar Int A = Bool
这意味着 Bar Int B
和 Bar Int C
不再定义。所以我猜想按照您的意图使用递归默认值的一种方法是重新定义特定的同义词(尽管它相当冗长):
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 = ()
关于haskell - 相互引用的默认类型实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12199324/