以下代码有什么问题:
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还很新,所以这个问题可能很简单......
谢谢! 克里斯
答案 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))”。