0

考虑以下代码,

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
4

1 回答 1

3

ExprTyp 不是(必然)一个单射类型函数。这意味着传递某种类型的东西ExprType m并不能确定m——也可能有不同n的类型ExprType n = ExprType m。这使 的类型expTypArg有点棘手:它以相同的方式使用返回类型多态性,例如,read确实如此,因此在您必须处理的相同情况下,您需要为其结果提供额外的类型注释read

于 2011-09-12T00:16:56.287 回答