我很好奇为什么我要写这个

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 𝔪 (α, β)

如果不清楚,请发表评论。

10-06 10:32