考虑以下代码,
data MyBaseExpr α where
ConstE :: Show α => α -> MyBaseExpr α
class Monad => MyMonadCls where
type ExprTyp :: * -> *
var :: String -> ExprTyp α -> (ExprTyp α)
expTypArg :: forall α. MyMonadCls => ExprTyp α -> α
expTypArg a = undefined
-- dummy type which will be used as an instance
newtype A α = A ( α)
然后,如果尝试使用expTypeArg函数编写实例,
instance forall . (Monad , Monad (A )) => MyMonadCls (A ) where
type ExprTyp (A ) = MyBaseExpr
var nme init@(expTypArg -> typb) =
return init
编译器抱怨
Couldn't match type `ExprTyp 0' with `MyBaseExpr'
Expected type: ExprTyp (A ) α
Actual type: ExprTyp 0 α
但是,如果添加一些范围类型表达式,
instance forall . (Monad , Monad (A )) => MyMonadCls (A ) where
type ExprTyp (A ) = MyBaseExpr
var nme init@((expTypArg :: MyMonadCls (A ) =>
ExprTyp (A ) α ->
(A α)) -> typb) =
return init
然后它解决得很好。解决ExprTyp == MyBaseExpr
的{{1}}问题是什么?
非常感谢,丹尼尔!在注意到只需要强制执行expTypArg
类型之后,这是一种消除部分废弃物的方法。
答案 0 :(得分:3)
ExprTyp不是(必然)一个内射型函数。这意味着,ExprType m
类型的某些内容并未确定m
- 可能还有n
个ExprType n = ExprType m
。expTypArg
。这使得read
的类型有点棘手:它以相同的方式使用返回类型多态,例如,read
,所以你需要在其结果中给出额外的类型注释与{{1}}有关的情况。