Difficulty understanding how to use filterM to compute powerset

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Difficulty understanding how to use filterM to compute powerset

Olumide
Dear List,

I'm trying to apply the following definition of filterM (from Brent
Yorgey's blog
https://byorgey.wordpress.com/2007/06/26/deducing-code-from-types-filterm/)

import Control.Monad  -- for liftM

filterM' :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
filterM' p [] = return []
filterM' p (x:xs) =
     let rest = filterM' p xs in
       do b <- p x
          if b then liftM (x:) rest
               else            rest

in order to understand how filterM can be used to compute the power set
of a list, as follows

    filterM' (const [False,True]) [1,2,3]

Where p in the filterM' is (const [False,True]). What confuses me is
that p x in filterM'. Based on my very limited understanding p x returns
b = [False, True]. How b be tested in the subsequent if-statement if it
is indeed a list? What am I getting wrong?

Regards,

- Olumide
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Difficulty understanding how to use filterM to compute powerset

David McBride
You are right, that the predicate in this case the argument is ignored.  In fact you can rewrite it and it would work the same.

filterM2' :: (Monad m) => (m Bool) -> [a] -> m [a]
filterM2' p [] = return []
filterM2' p (x:xs) =
    let rest = filterM2' p xs in
      do b <- p
         if b then liftM (x:) rest
              else            rest


   filterM2' [False,True] [1,2,3]

As for how this works, remember that lists are Monads and their instance makes them work like list comprehensions.  Consider the following.

test2 :: [(Int,Int)]
test2 = do
  x <- [1,2]
  y <- [3,4]
  return (x,y)

[(1,3),(1,4),(2,3),(2,4)]

test3 :: [String]
test3 = do
  x <- [True, False, True]
  if x
    then ["x was true"]
    else ["x was false"]

["x was true","x was false", "x was true"]

So the List Monad instance pairs each element with every other element, returning a list of every case.  In filterM's case, it checks each x and based on that does something slightly different.  In fact what it is doing is giving you two cases, one where x is there and one where it isn't, then running the same function on the remaining elements once for each of those two cases to fill in the remaining cases, appending all the results together.  In my opinion it is easier to understand by just playing with it.

filterM2' [True,True] [1,2]
[[1,2],[1,2],[1,2],[1,2]]

filterM2' [True,False] [1,2]
[[1,2],[1],[2],[]]

filterM2' [False,True] [1,2]
[[],[2],[1],[1,2]]

filterM2' [False,False] [1,2]
[[],[],[],[]]

On Sun, Jun 17, 2018 at 9:24 AM, Olumide <[hidden email]> wrote:
Dear List,

I'm trying to apply the following definition of filterM (from Brent Yorgey's blog https://byorgey.wordpress.com/2007/06/26/deducing-code-from-types-filterm/)

import Control.Monad  -- for liftM

filterM' :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
filterM' p [] = return []
filterM' p (x:xs) =
    let rest = filterM' p xs in
      do b <- p x
         if b then liftM (x:) rest
              else            rest

in order to understand how filterM can be used to compute the power set of a list, as follows

   filterM' (const [False,True]) [1,2,3]

Where p in the filterM' is (const [False,True]). What confuses me is that p x in filterM'. Based on my very limited understanding p x returns b = [False, True]. How b be tested in the subsequent if-statement if it is indeed a list? What am I getting wrong?

Regards,

- Olumide
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners


_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners