【问题标题】:Error on comparing IO Int inside of a lambda比较 lambda 内部的 IO Int 时出错
【发布时间】:2014-07-27 10:29:22
【问题描述】:

我有一小段代码要在 if 语句中使用。代码是

getRandomInt :: (Int, Int) -> IO Int
getRandomInt (a, b) = do
    g <- newStdGen
    return . fst $ randomR (a, b) g

然后再往下……

if ((getRandomInt (0,1)) >>= (\x -> x == 1))

根据我的理解,这应该编译成 randomInt == 1 并且可以在 if 语句中使用。反而;我收到此错误:

word.hs:30:21:
    Couldn't match expected type `Bool' with actual type `IO b0'
    In the expression: ((getRandomInt (0, 1)) >>= (\ x -> x == 1))
    In a stmt of a 'do' block:
      if ((getRandomInt (0, 1)) >>= (\ x -> x == 1)) then
          getRandomVowel : (getWord $ len - 1)
      else
          getRandomConsonant : (getWord $ len - 1)
    In the expression:
      do { if ((getRandomInt (0, 1)) >>= (\ x -> x == 1)) then
               getRandomVowel : (getWord $ len - 1)
           else
               getRandomConsonant : (getWord $ len - 1) }

很抱歉造成任何明显的误解,我昨天才开始学习 Haskell。

【问题讨论】:

    标签: haskell io lambda int


    【解决方案1】:

    (&gt;&gt;=) 的类型是Monad m =&gt; m a -&gt; (a -&gt; m b) -&gt; m b。在这种情况下m = IO

    所以你有两个问题:

    首先,\x -&gt; x == 1 将返回 Bool,而不是 IO Bool,因此它不适合作为 (&gt;&gt;=) 的第二个参数。

    您可以通过将其更改为 \x -&gt; return (x == 1) 来轻松解决此问题,但这不是一个非常干净的解决方案,然后您会发现结果类型为 IO Bool,而不是 Bool

    这就是类型错误告诉你的 - if 需要一个 Bool 参数,但它得到了 IO something

    最干净的解决方案是将getRandomInt 调用提升到单独的&lt;- 行:

    x <- getRandomInt (0,1)
    if x == 1 then ...
    

    【讨论】:

    • 我尝试按照您的建议进行操作,但这只会给我一个更神秘的错误,我已将其编辑到第一篇文章中。
    • 这是getWord 中的另一个问题。尝试将其类型更改为 IO [Char] 而不是 [IO Char] - 这是两个非常不同的东西。您还需要在 ifotherwise 案例的每个分支周围的正文中添加一些 returns。
    • 哦,我知道我在函数的其余部分做错了什么。一旦我修复了它的其余部分,我将更多地研究这个错误。除非此错误源于此功能被破坏。
    • 另外,在这种情况下,你真的应该针对不同的问题提出不同的问题,否则很难遵循问题/答案流程。
    • 我不知道单独的错误是另一个问题的一部分。我会编辑它的问题。
    【解决方案2】:

    ((getRandomInt (0,1)) &gt;&gt;= (\x -&gt; x == 1)) 不起作用,因为&gt;&gt;= 具有类型(此处专门为IO):IO a -&gt; (a -&gt; IO b) -&gt; IO b,但(\x -&gt; x==1) 具有类型(此处专门为Int):Int -&gt; Bool ,所以你的类型不匹配。 这个问题很容易解决,这里实际上有一个函数可以应用纯函数:liftM :: Monad m =&gt; (a-&gt;b) -&gt; m a -&gt; m b(如果你听说过,它几乎等同于fmap)。

    第二个问题是,即使您解决了问题,您仍然不能在 if 语句中使用 IO Bool 代替 Bool(这是错误所抱怨的;类型检查器没有在发现类型不可能正确之前,实际上并没有那么远)。

    如果可能的话,我个人的建议是暂时远离IO;它的工作方式与您在命令式语言中习惯使用的完全不同,您需要对 Haskell 有更好的了解才能完全理解它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 2011-08-26
      • 2023-03-29
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      相关资源
      最近更新 更多