1

以下代码有什么问题:

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还是很陌生,所以这个问题可能很简单......

谢谢!克里斯

4

3 回答 3

9

你不应该在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内部的数据结构,那么您可能做错了什么(可能在您想要调用的代码中)这来自)。

于 2013-05-09T16:18:33.530 回答
1

就像xtype一样IO a,不需要重新返回它,这与绝对需要注入 monad 的元组相反。

if f s then return $ (x, xs)

但是,这不是唯一的问题,因为您进入了IOmonad 并且您的签名没有反映它,因为您返回的类型(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 -> Bool) -> [a] -> (a, [a]),然后 usingreturn就足以构建它的一元版本。nextMatchIO = return $ nextMatch然后使用由Control.Monad.

于 2013-05-09T16:03:43.003 回答
-1

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

于 2013-05-09T16:00:56.460 回答