I believe what you had in mind
filterM f list = foldr foldFn (return []) list
not xs at the end, so I will take that in the future.
The problem you are facing is that the type variables in the tick signature foldFn completely separate from the type variables in the signature of the filterM type. This is really equivalent to saying
filterM :: (Monad m) => (a -> (m Bool)) -> [a] -> m [a] filterM f list = foldr foldFn (return []) list where foldFn :: (Monad m1) => a1 -> m1 [a1] -> m1 [a1] foldFn x acc = let m = fx in acc >>= \l -> m >>= \b -> (if b == True then return (x:l) else return l)
But you use f in the definition of foldFn , which says that m1 should be the same as m from above. You do not want the foldFn type foldFn work on any Monad , only the Monad that uses f . This is a subtle difference, and difficult to determine first. This also applies to the difference between a and b in the two signatures. You can simply remove the type signature for foldFn , and GHC can correctly infer the type foldFn , but in cases where this does not work, you can use the ScopedTypeVariables extension. I would not recommend using it in this case, but there are times when it is really useful or even necessary:
{-
And now m and a in both type signatures refer to the same type variables. I will also let hlint report some improvements that can be made to your code, for example, moving the return from if on the last line using the do notation for foldFn and eta-reduction filterM to make the list argument implicit, and also remove some unnecessary parentheses .
source share