【问题标题】:error message when implementing `((->) r)` monad (type mismatch)实现 `((->) r)` monad 时出现错误消息(类型不匹配)
【发布时间】:2019-03-27 02:57:53
【问题描述】:

我刚开始学习haskell,我正在尝试实现一些常见的单子作为自己的练习。当我摆弄((->) r) monad 时,我实现了这个(错误的)定义:

instance Monad ((->) r) where
   return x = \_ -> x
   m >>= f = \c -> (f . m) c

GHCi 向我抱怨

• Couldn't match expected type ‘b’ with actual type ‘t -> b’
  `b’ is a rigid type variable bound by
    the type signature for:
      (>>=) :: forall a b. (t -> a) -> (a -> t -> b) -> t -> b

而类型应该是:

(>>=) :: (t -> a ) -> (a -> t -> b) -> t -> b

为什么我的实现会破坏它?看起来,forall 版本应该给出完全相同的类型,但 GHCi 不这么认为。有什么区别?

【问题讨论】:

  • 你在哪里看到存在量化?
  • @melpomene 抱歉,如果我使用了错误的术语。我的定义中没有使用存在量化,但 GHC 认为类型签名包括 forall a b.
  • 提示:在m >>= \x -> f x 中,m 需要r,但f x 也是如此。
  • 为什么你的>>= 有非标准类型?您是否定义了自己的 >>= 并翻转了参数?
  • forall 无关紧要。错误消息显示所有类型变量的显式声明,但(>>=) :: (a -> t -> b) -> (t -> a) -> t -> b 的含义完全相同。真正的问题是类型应该是(>>=) :: (t -> a) -> (a -> t -> b) -> t -> b(即(>>=) :: (Monad m) => m a -> (a -> m b) -> m bm = ((->) t))。为什么不是?

标签: function haskell monads


【解决方案1】:

我的致命误解是我认为错误消息意味着我的实现具有不正确的类型签名。 (我认为这是因为类型签名中有一个forall。)事实证明这不是实际的错误,而我在实现中的错误是我需要将另一个r 术语应用于f 和@ 987654324@ 在我的实现中。感谢@luqui 和@melpomene 向我指出这一点

【讨论】:

  • 您能否接受这个答案,使其不再显示为“未回答”?
  • @bradrn 我不能在 2 天后这样做,然后我会这样做
  • 哦,我不知道。我最好在添加这些类型的 cmets 时更加小心。
  • 我不确定这是否真的值得自我回答。 Monad ((->) r) 的正确实例已广泛可用。
  • @chepner 是的,我想我的主要学习是如何阅读错误消息。也许可以编辑问题以反映这一点,甚至删除?你怎么看?
猜你喜欢
  • 2021-07-14
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多