简体   繁体   中英

Generate a list from another function which returns a Bool in Haskell

i'm currently working on lists of lists (which we use to represent a grid). I have one function which receive 2 arguments (my grid and a tuple of 4 Integers) and it returns a Boolean.

Now with a new function, I need to generate a list of every tuples which returns True for a certain grid. For exemple, function1 (1,3,2,2) grid1 will return True so I need to get (1,3,2,2) in my list.

The other problem is that I have multiple conditions to respect for my tuple (a,b,c,d) of 4 Integers such as : 1 <= a < a+c <= n and 1 <= b < b+d <= m where n is the number of lines (so length grid) and m is the number of columns (so length (head grid)).

I had the idea to use map but so far I never used it in such a situation and everything I tried failed.

Thanks

There are two basic approaches for doing this in Haskell.

  1. Generate a stream of tuples that satisfy the constaints you listed but don't necessarily return true according to the function
  2. Use filter to par down the list

Or we can try to avoid generating all that redundant data and just have something like

  1. Use our knowledge of the predicate to only generate a stream of valid tuples in the first place

Since we're working with an arbitrary function, we can't really do the second so we'll opt for the former. Thus we start by generating all of the tuples satisfying the constaints 1 <= a < a + c <= n and 1 <= b < b + d <= m .

Now it's clear that a is in the range [1 .. n] and b is in [1 .. m] . Furthermore, for each a we can have c in [a + 1 .. n - a] and for each b we can have [b + 1 .. m - b] . We'll use Haskell's list comprehensions to encode this is a very snazzy way

allTuples :: Int -> Int -> [(Int, Int, Int, Int)]
allTuples n m = -- First we take in n, m
  [(a, b, c, d) |
    a <- [1 .. n],
    b <- [1 .. m],
    c <- [a + 1 .. n - a],
    d <- [b + 1 .. m - b]]

Here these <- will do the right thing and take all possible combinations. Next all we need do is use filter to remove elements.

 prune :: Grid -> [(Int, Int, Int, Int)] -> [(Int, Int, Int, Int)]
 prune grid tuples = filter (\t -> f grid t) tuples
 -- could have written:
 -- prune grid = filter (f grid)
 -- prune = filter . f

Then we can glue them together, but I'll leave this final step to you because I'm not sure how you'll use it in your application. You can also merge these steps into a single list comprehension:

allTuples :: Int -> Int -> [(Int, Int, Int, Int)]
allTuples n m = -- First we take in n, m
  [(a, b, c, d) |
    a <- [1 .. n],
    b <- [1 .. m],
    c <- [a + 1 .. n - a],
    d <- [b + 1 .. m - b],
    f grid (a, b, c, d)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM