【问题标题】:Haskell IO function type mismatchHaskell IO 函数类型不匹配
【发布时间】:2013-05-04 04:12:33
【问题描述】:

以下代码有什么问题:

nextMatch :: (a -> Bool) -> [IO a] -> (IO a, [IO a])
nextMatch f (x:xs) = do
    s <- x
    if f s then (return x, xs)
        else nextMatch f xs

编译错误说:

src\Main.hs:364:10:
    Couldn't match expected type `(IO a, t0)' with actual type `IO a'
    In a stmt of a 'do' block: s <- x
    In the expression:
      do { s <- x;
           if f s then (return x, xs) else nextMatch f xs }
    In an equation for `nextMatch':
        nextMatch f (x : xs)
          = do { s <- x;
                 if f s then (return x, xs) else nextMatch f xs }

我想要一个函数,它在列表中搜索匹配项并将匹配的元素和剩余的列表作为元组返回。

我对haskell还是很陌生,所以这个问题可能很简单......

谢谢! 克里斯

【问题讨论】:

  • 一般性评论——一元论点(例如IO [a],或您的[IO a])几乎总是一个坏主意。不纯代码通常采用纯参数,使用 do-notation 或 &gt;&gt;= 将它们应用到一元值。

标签: haskell io functional-programming tuples monads


【解决方案1】:

你的函数应该返回一个元组。如果我的 Haskell 仍然达到标准,我会尝试在您的返回函数“if f s then (return (x, xs))”周围加上括号。

【讨论】:

  • 你的 Haskell 还没有“达到标准”:)
【解决方案2】:

作为 x 如果是 IO a 类型,则无需重新返回它,这与绝对需要注入 monad 的元组相反。

if f s then return $ (x, xs)

但是,这不是唯一的问题,因为你在 IO monad 中并且你的签名没有反映它,因为你的返回类型是 (IO a, [IO a]) 它应该是 IO (IO a, [IO a])。 那么你的代码应该如下。

nextMatch :: (a -> Bool) -> [IO a] -> IO (IO a, [IO a])
nextMatch f (x:xs) =  
  do 
    done <- fmap f x  
    if done
    then return $ (x, xs)
    else nextMatch f xs 

无论如何,我不知道您要做什么,但是您的函数签名看起来很尴尬。它应该看起来更像nextMatch :: (a -&gt; Bool) -&gt; [a] -&gt; (a, [a]),然后使用return 就足以构建它的一元版本。 nextMatchIO = return $ nextMatch 然后使用Control.Monad 提供的其他函数将此计算插入到您的控制流中。

【讨论】:

  • 你是对的,但是为了避免额外的计算对我的大脑来说是痛苦的,我参加了大部分时间我会使用return $ expr 代替return expr 的聚会。当然,这个规则在我写专业代码的时候是不适用的,那我就抽空问我是否必须使用$。无论如何感谢您的发言。
  • @zurgl 我最近得出的结论是,我需要在 monadic 代码中使用 $ much less。将东西转移到使用&gt;&gt;= 或应用风格是很痛苦的,因为我一直认为我可以将a &lt;- g $ b; f a 转换为g $ b &gt;&gt;= ff &lt;$&gt; g $ b
【解决方案3】:

您不需要在这里处理IO。这就是我将它实现为纯函数的方式(我添加了Maybe 类型,因为可能没有下一个匹配项):

nextMatch :: (a -> Bool) -> [a] -> Maybe (a, [a])
nextMatch _ []     = Nothing
nextMatch f (x:xs) = if f x then Just (x, xs) else nextMatch f xs

作为初学者,如果您将带有 IO 的东西作为函数的输入,或者如果您要返回带有 IO 的数据结构,那么您可能做错了什么(可能在您想要调用它的代码中)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-24
    • 2014-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 2014-03-02
    相关资源
    最近更新 更多