【问题标题】:Could not deduce (m ~ m1)无法推断 (m ~ m1)
【发布时间】:2013-07-21 04:07:09
【问题描述】:

在 GHC 中编译此程序时:

import Control.Monad

f x = let
  g y = let
    h z = liftM not x
    in h 0
  in g 0

我收到一个错误:

test.hs:5:21:
    Could not deduce (m ~ m1)
    from the context (Monad m)
      bound by the inferred type of f :: Monad m => m Bool -> m Bool
      at test.hs:(3,1)-(7,8)
    or from (m Bool ~ m1 Bool, Monad m1)
      bound by the inferred type of
               h :: (m Bool ~ m1 Bool, Monad m1) => t1 -> m1 Bool
      at test.hs:5:5-21
      `m' is a rigid type variable bound by
          the inferred type of f :: Monad m => m Bool -> m Bool
          at test.hs:3:1
      `m1' is a rigid type variable bound by
           the inferred type of
           h :: (m Bool ~ m1 Bool, Monad m1) => t1 -> m1 Bool
           at test.hs:5:5
    Expected type: m1 Bool
      Actual type: m Bool
    In the second argument of `liftM', namely `x'
    In the expression: liftM not x
    In an equation for `h': h z = liftM not x

为什么?此外,为f (f :: Monad m => m Bool -> m Bool) 提供显式类型签名会使错误消失。但这与 Haskell 自动为 f 推断的类型完全相同,根据错误信息!

【问题讨论】:

  • 单态限制?
  • 单态限制只适用于简单的模式绑定,这里没有。反正加-XNoMonomorphismRestriction是没有效果的。
  • 我认为它与 let-generalization 有关,因为错误随着 -XMonoLocalBinds 而消失

标签: haskell


【解决方案1】:

实际上,这很简单。 let-bound 变量的推断类型被隐式推广到类型方案,所以你的方式有一个量词。 h的广义类型为:

h :: forall a m. (Monad m) => a -> m Bool

f的广义类型是:

f :: forall m. (Monad m) => m Bool -> m Bool

他们不一样m。如果你这样写,你会得到基本上相同的错误:

f :: (Monad m) => m Bool -> m Bool
f x = let
  g y = let
    h :: (Monad m) => a -> m Bool
    h z = liftM not x
    in h 0
  in g 0

您可以通过启用“作用域类型变量”扩展来修复它:

{-# LANGUAGE ScopedTypeVariables #-}

f :: forall m. (Monad m) => m Bool -> m Bool
f x = let
  g y = let
    h :: a -> m Bool
    h z = liftM not x
    in h 0
  in g 0

或者通过使用“单态本地绑定”扩展名MonoLocalBinds禁用let-generalisation。

【讨论】:

  • 这不是那么简单,因为使用ghc <= 7.6.1,即使使用明确的NoMonoLocalBinds,问题也不会出现。行为随着 7.6.2 改变,不知道是有意还是无意。
  • 为什么f x = let g y = liftM not x in g 0 没有发生这种情况? g的类型应该用同样的方式泛化。
  • 那么可能是一个错误。在这种情况下,问题和答案是一个很好的重现案例和开始寻找的地方。
猜你喜欢
  • 2018-11-21
  • 2021-04-10
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-01
  • 1970-01-01
相关资源
最近更新 更多