我很好奇为什么我要写这个
instance (HzMonad 𝔪, Data.Suitable.Suitable 𝔪 α, γ ~ ExprTyp 𝔪 α) => VarDecl 𝔪 γ where
var = varhz
代替这个
instance (HzMonad 𝔪, Data.Suitable.Suitable 𝔪 α) => VarDecl 𝔪 (ExprTyp 𝔪 α) where
var = varhz
-- error
Hz2/Language.hs:114:53:
Illegal type synonym family application in instance: ExprTyp 𝔪 α
In the instance declaration for `VarDecl 𝔪 (ExprTyp 𝔪 α)'
在哪里
varhz ::
(HzMonad 𝔪, Data.Suitable.Suitable 𝔪 α) =>
String -> ExprTyp 𝔪 α -> 𝔪 (ExprTyp 𝔪 α)
波浪线到底是什么?非常感谢。
最佳答案
我认为问题在于=>
必须是类型构造函数或类型变量。 ExprTyp可以引用多个差异类型构造函数。用等式约束代替它确实可以工作,但是生成的实例实际上是无用的,因为假定编译器是ExprTyp,则编译器将无法推断出有关γ
的任何内容-ExprTyp可以别名为任何内容。
在我的情况下(我正在尝试编写DSL monad),解决方案是将所有相关类型的用法包装在newtype构造函数中。例如,如果我们以
class MyDSL m a where
type ExprTyp m :: * -> *
printE :: ExprTyp m a -> m ()
然后将其包装会导致
newtype ExprT a = ExprT a
class MyDSL m a where
type ExprTyp m :: * -> *
printE :: ExprT (ExprTyp m a) -> m ()
然后,例如,变量声明(我正在编写元组变量声明的代码)可能是,
instance (HzMonad 𝔪, Data.Suitable.Suitable 𝔪 α, γ ~ ExprTyp 𝔪 α) => VarDecl 𝔪 (ExprT γ)
instance (Monad 𝔪, VarDecl 𝔪 α, VarDecl 𝔪 β) => VarDecl 𝔪 (α, β)
如果不清楚,请发表评论。