0

我是一个初学者,我正在尝试使用Hoed来跟踪 Haskell 评估,因为它可能会进一步帮助我的学习过程。

我在他们的示例代码中看到了这样的

isEven :: Int -> Bool
isEven = observe "isEven" isEven'
isEven' n = mod2 n == 0

我在想如何才能observe跟踪实例定义的函数>>=,例如。

我写了类似的东西

bind' = observe "bind'" (>>=)

当然我有一个错误

* Ambiguous type variable 'm0' arising from a use of '>>='
  prevents the constraint '(Monad m0)' from being solved.
  Relevant bindings include
    bind' :: m0 a0 -> (a0 -> m0 b0) -> m0 b0 (bound at my.hs:46:1)
  Probable fix: use a type annotation to specify what 'm0' should be.
  These potential instances exist:
  ...

我应该/如何使用类型注释来指定哪个Monad实例的(例如 Reader、State 等)>>=函数

4

1 回答 1

1

看起来你已经找到了臭名昭著 MonomorphismRestriction的. 更多 信息。这些链接很好地解释了 MonomorphismRestriction 是什么以及它是如何工作的。

你期望bind'没有签名的写作应该“正常工作”并没有错。但是,有时编译器需要一些帮助。简而言之,由于 MonomorphismRestriction,GHC 尝试采用名义上的多态签名bind' :: Monad m => m a -> (a -> m b) -> m b,并通过实例化一些类型变量来降低其多态性。

在您的情况下,编译器似乎只想让bind'一个特定的Monad m. 如果没有您的真实代码,我不能肯定地说,但请考虑以下示例:

import Debug.Trace

main :: IO ()
main = (>>=) (return "hello") print

bind' = trace "bind" (>>=)

编译器会产生与您类似的错误:Ambiguous type variable m0

但是,如果您使用 bind'

import Debug.Trace

main :: IO ()
main = bind' (return "hello") print

bind' = trace "bind" (>>=)

没有错误!那是因为 GHC推断应该mIO因为bind'IOmonad 中使用。

或者,您可以告诉 GHC 关闭 MonomorphismRestriction:

{-# LANGUAGE NoMonomorphismRestriction #-}

import Debug.Trace

main :: IO ()
main = (>>=) (return "hello") print

bind' = trace "bind" (>>=)

它编译得很好!

于 2019-02-15T19:41:38.363 回答