Haskell IO函数类型不匹配

时间:2013-05-09 15:54:19

标签: haskell io functional-programming tuples monads

以下代码有什么问题:

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

谢谢! 克里斯

3 个答案:

答案 0 :(得分: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的数据结构,那么很可能是可能做错了什么(可能是你想从中调用它的代码)。

答案 1 :(得分:1)

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 -> Bool) -> [a] -> (a, [a]),然后使用return足以构建它的monadic版本。 nextMatchIO = return $ nextMatch然后使用Control.Monad提供的其他函数将此计算插入到您的控制流中。

答案 2 :(得分:-1)

你的功能应该是返回一个元组。如果我的Haskell仍然达到标准,我会尝试在你的返回函数周围放置一些parens“if f s then(return(x,xs))”。