Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a function using bind (>>=)

I wrote a filter function:

f :: (a -> Bool) -> [a] -> [a]
f p xs = case xs of
         [] -> []
         x : xs' -> if p x
                    then x : f p xs'
                    else f p xs'

To understand bind, I want to implement this using bind. What I was thinking about:

f p xs = xs >>= (\x xs -> if p x then x : f p xs else f p xs)

But I get this error:

* Couldn't match expected type `[a]' with actual type `[a] -> [a]'
    * The lambda expression `\ x xs -> ...' has two arguments,
      but its type `a -> [a]' has only one
      In the second argument of `(>>=)', namely
        `(\ x xs -> if p x then x : f p xs else f p xs)'
      In the expression:
        xs >>= (\ x xs -> if p x then x : f p xs else f p xs)
    * Relevant bindings include
        xs :: [a] (bound at <interactive>:104:5)
        p :: a -> Bool (bound at <interactive>:104:3)
        f :: (a -> Bool) -> [a] -> [a] (bound at <interactive>:104:1)

Successfully did it using foldr:

f p xs = foldr (\x xs -> if p x then x : f p xs else f p xs) [] xs

What's going wrong?

like image 977
V0lvox337 Avatar asked Mar 04 '23 17:03

V0lvox337


1 Answers

To understand bind, i want to implement this as bind.

There is no bind here. The bind is added in case of a do expression. The above is not a do-expression, so there is no bind here.

You can however write this with bind, like:

f p xs = xs >>= \x -> if p x then [x] else []

but this is not a literal mapping of the original function, we simply make use of the instance Monad [] implementation here. Nevertheless, your f is just filter :: (a -> Bool) -> [a] -> [a] here.

like image 174
Willem Van Onsem Avatar answered Mar 13 '23 08:03

Willem Van Onsem