我该怎么做才能使这个ghci推断签名编译

时间:2014-09-12 06:38:35

标签: haskell ghc type-inference ghci

我有一个RWST Monad,并且有一些泛型函数可以与Writer部分进行交互。

作为参考,RWST是这样的:

newtype RWST r w s m a = RWST {runRWST :: r -> s -> m (a, s, w)}
instance (Monoid w, Monad m) => Monad (RWST r w s m)
instance Functor m => Functor (RWST r w s m)
instance (Monoid w, MonadFix m) => MonadFix (RWST r w s m)
instance (Monoid w, MonadPlus m) => MonadPlus (RWST r w s m)
instance Monoid w => MonadTrans (RWST r w s)
instance (Monoid w, MonadIO m) => MonadIO (RWST r w s m)
instance (Monoid w, Monad m) => MonadWriter w (RWST r w s m)
instance (Monad m, Monoid w) => MonadState s (RWST r w s m)
instance (Monad m, Monoid w) => MonadReader r (RWST r w s m)
instance (Monoid w, Monad m) => MonadRWS r w s (RWST r w s m)

所以我有一个像这样的数据Definition

type Definition = RWS SapphireReader DefWriter DefState

DefWriter只是type DefWriter = Seq Error (错误由我定义,而不是Control.Monad.Error

我有一个工作职能:

tellPError :: Position -> ParseError -> Definition ()
tellPError posn err = tell (singleton $ PError posn err)

现在我需要一个新的RWST并希望拥有泛型 tellPError,我尝试删除签名,在 ghci 中加载文件并执行{{ 1}}。

:t tellPError

我尝试在代码中给我的函数签名,它不会编译:

λ :t tellPError
tellPError :: MonadWriter (Seq Error.Error) m => Position -> ParseError -> m ()

我真的需要这面旗帜吗?我尝试了它,它确实编译但不起作用。

2 个答案:

答案 0 :(得分:2)

问题在于,根据Haskell的2010年报告部分4.1.24.1.3,类约束必须采用以下形式:

class   →   qtycls tyvar
        |   qtycls ( tyvar atype1 … atypen )        (n ≥ 1) 

qtycls是一个类名,tyvar是一个类型变量,而atype基本上几乎都是任何类型。但请注意,这两个规则的格式均为qtycls (? tyvar ...

但该签名包含约束:

MonadWriter (Seq Error.Error) m

其形式如下:

qtycls (gtycon1 gtycon2) tyvar

因此错误:gtycon1 s应该是类型变量,而不是类型构造函数。 为了表达该约束,您必须使用-XFlexibleContexts扩展名。

另一种方法是通过指定所需的monad m来消除约束,从而减少多态性。

答案 1 :(得分:0)

好的,我现在一直在关注这个问题,并提出了在RWS右侧指定=>的想法,这似乎可以解决问题:

tellPError :: Position -> ParseError -> RWS r (Seq Error) s ()
tellPError posn err = tell (singleton $ PError posn err)

编译并运用它的方式!