我想我发现了一个“不存在的单子”

2024-01-27

我发现 Haskell 的一个奇怪的特性让我相信我的思考方式是错误的。我认为在Haskell中,应该有一些“不存在的”单子。这是因为以下原因。

Prelude> return 1
1
Prelude> return 1 >>= \x -> if even x then return True else return False
False

>>=属于类型m a -> (a -> m b) -> m b where m可以是任何单子。我的理论是这样的:因为return 1评估为仅仅1, return 1可以被认为是1提升到包裹在 a 内的值“不存在的”单子。 Haskell 捕获了这个事实并评估了整个表达式

return 1 >>= \x -> if even x then return True else return False

to False因为它必须产生一个“不存在的False"这只是一个False.

不过,我从来没有听说过这样的事情“不存在的”之前的单子。

我确信我的理论是错误的,因为如果“不存在的1"只是1,下面的表达式必须是类型一致的,但事实并非如此。它是上述版本的修改版本。

1 >>= \x -> if even x then return True else return False

<interactive>:57:1: error:
    • Could not deduce (Integral a0)
      from the context: (Monad m, Integral a, Num (m a))
        bound by the inferred type for ‘it’:
                   forall (m :: * -> *) a. (Monad m, Integral a, Num (m a)) => m Bool
        at <interactive>:57:1-56
      The type variable ‘a0’ is ambiguous
    • In the ambiguity check for the inferred type for ‘it’
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      When checking the inferred type
        it :: forall (m :: * -> *) a.
              (Monad m, Integral a, Num (m a)) =>
              m Bool

所以,我的理论一定是有矛盾的。我缺少什么?


return 1不只是1。你所认为的“不存在的单子”实际上是IO。当你使用return 1,GHCi 假设您的意思是IO,然后帮助执行 IO 表达式并显示结果。你会得到一个类型错误1 >>= ...因为1不是一个单子。

As @bradrn https://stackoverflow.com/users/7345298/bradrn提及在评论中 https://stackoverflow.com/questions/57899103/i-think-i-found-a-non-existent-monad#comment102219158_57899118,一般来说,GHCi 会自动运行任何IO a你给它的值,然后打印出该值it返回;如果你给 GHCi 一个非IO输入值,它只会打印该值(如果可以的话)。

顺便说一句,有一个 monad 叫做Identity正如你所说,它本质上确实作为一个“不存在的单子”起作用,因为return x同构于x不管你往里面放什么。但它不会自动被使用;您需要手动包装和打开它才能使用它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我想我发现了一个“不存在的单子” 的相关文章

随机推荐