“引用”类型类函数

时间:2019-02-14 15:55:46

标签: haskell monomorphism-restriction

我是一个初学者,我正在尝试使用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实例(例如,读者,州等)的>>=功能

1 个答案:

答案 0 :(得分:1)

您似乎已找到infamous MonomorphismRestrictionMore 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" (>>=)

它编译就可以了!