Reputation: 2249
what is the problem with the following code:
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
The compile error says:
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 }
I want a function which searches a list for a match and returns the matched element plus the remaining list, as tuple.
I am still quite new to haskell, so this problem might be something quite simple...
Thanks! Chris
Upvotes: 1
Views: 223
Reputation: 139930
You shouldn't need to deal with IO
here. This is how I'd implement it as a pure function (I added the Maybe
type since there might not be a next match):
nextMatch :: (a -> Bool) -> [a] -> Maybe (a, [a])
nextMatch _ [] = Nothing
nextMatch f (x:xs) = if f x then Just (x, xs) else nextMatch f xs
As a beginner, if you're taking something with IO
as an input to a function, or if you're returning a data structure with IO
inside of it, chances are you're probably doing something wrong (probably in the code you want to call this from).
Upvotes: 9
Reputation: 1930
As x
if of type IO a
, no need to re-return it, contrary to the tuple which definitely need to be injected into the monad.
if f s then return $ (x, xs)
But, that not the only issue, as your are into the IO
monad and your signature doesn't reflect it, as you return type is (IO a, [IO a])
it should be IO (IO a, [IO a])
.
Then your code should be as follow.
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
Anyway I don't know what you are trying to do but the signature of your function look pretty awkward. It should look much more like nextMatch :: (a -> Bool) -> [a] -> (a, [a])
, then using return
is enough to build a monadic version of it. nextMatchIO = return $ nextMatch
and then plug this computation into your control flow using other function, provided by Control.Monad
.
Upvotes: 1
Reputation: 119
Your function should be returning a tuple. If my Haskell is still up to par, I would try putting parens around your return function "if f s then (return (x, xs))".
Upvotes: -1