考虑以下代码,
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
解决什么问题expTypArg
?
编辑
非常感谢,丹尼尔!在注意到只强制执行需要的类型之后,这是一种去掉一些冗长的方法。
ignore_comp :: α -> β -> β
ignore_comp a b = b
instance forall . (Monad , Monad (A )) => MyMonadCls (A ) where
type ExprTyp (A ) = MyBaseExpr
var nme init@(expTypArg -> typb) =
typb `ignore_comp`
return init