我是一个初学者,我正在尝试使用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
实例(例如,读者,州等)的>>=
功能
答案 0 :(得分:1)
您似乎已找到infamous MonomorphismRestriction
。 More info。这些链接在解释什么是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 推断 m
应该是IO
,因为bind'
单子中使用了IO
。
或者,您可以告诉GHC关闭MonomorphismRestriction:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Debug.Trace
main :: IO ()
main = (>>=) (return "hello") print
bind' = trace "bind" (>>=)
它编译就可以了!