1

So i currently have this function for generating all possible combinations

func :: [a] -> [b] -> [(a, b)]
func xs ys = concat(map (\x -> map (\y -> (x,y))ys) xs)

Now I want to extend it so that i can filter it using an anonymous function as parameter.

Example:

func [1,2,3] [4,5] (\ a b -> a+b > 6) -> [(2,5),(3,4),(3,5)]

I tried to change the Typesignature of func:

from: [a] -> [b] -> [(a, b)]

to: [a] -> [b] -> (a1 -> a1 -> Bool) -> t

But it did not work.

Thank you in advance!

RLP
  • 84
  • 6
  • 2
    Just changing the signature is not enough, you'll have to accept the fucntion and apply it somewhere in the definition of your function. – cafce25 Nov 24 '22 at 12:56
  • 1
    The last signature is way too general: it claims that given any two lists of type `[a]` and `[b]`, and a function `a1->a1->Bool` (where `a1` is a completely arbitrary type, unrelated to the previous lists), will produce a result of an arbitrary type `t` (caller's choice!). That can't be correct. Probably you want `[a] -> [b] -> (a->b->Bool) -> [(a,b)]`. To implement this I'd use something involving `zip`. – chi Nov 24 '22 at 12:58
  • Thank you for the reply :) So now I have this: `func :: [a] -> [b] -> ((a,b) -> Bool) -> [(a, b)]` `func xs ys f = filter f (tup)` `where` `tup = concat(map (\x -> map (\y -> (x,y))ys) xs)` But when I run it i get an error: • Couldn't match expected type ‘Bool’ with actual type ‘(a, b) -> Bool’ • The lambda expression ‘\ a b -> a + b > 7’ has two value arguments, but its type ‘(a, b) -> Bool’ has only one What am i doing wrong? Thanks in advance! – RLP Nov 24 '22 at 13:38

1 Answers1

3

OP has stated that they changed their code to

func :: [a] -> [b] -> ((a,b) -> Bool) -> [(a, b)]
func xs ys f = filter f (tup)
  where tup = concat(map (\x -> map (\y -> (x,y))ys) xs)

followed by what one assumes is

func [1,2,3] [4,5] (\a b -> a + b > 7)

which gives them the error

• Couldn't match expected type ‘Bool’ with actual type ‘(a, b) -> Bool’
• The lambda expression ‘\ a b -> a + b > 7’ has two value arguments, but its type ‘(a, b) -> Bool’ has only one

This is easy to fix; in fact the error message is relatively clear as GHC error messages go. (That's faint praise, admittedly.) Doing this instead should work, though I'm away from a Haskell compiler and can't run it:

func [1,2,3] [4,5] (\(a, b) -> a + b > 7)

Explanation: \a b -> a + b > 7 is an anonymous function taking two arguments, a and b, whereas \(a, b) -> a + b > 7 is an anonymous function taking a single argument which is a pair. The type of the last argument of func, ((a, b) -> Bool), is the type of the second anonymous function, not the first.

(This problem can also be fixed by making func's last argument be of type a -> b -> Bool, while passing the first anonymous function.)

I originally thought OP's tup was just zip, and recommended they use zip instead to improve legibility. OP correctly points out that their function has very little in common with zip except the type. There may still be a legibility win to be had, though; see this.

neofelis
  • 610
  • 4
  • 5
  • 1
    But my function is not really Zip. Zip makes a list of tuples, each tuple containing elements of both lists occurring at the same position. But my function generates something like a Cartesian product from the 2 lists. – RLP Nov 24 '22 at 15:10
  • 1
    Oh, whoops! I'll edit. – neofelis Nov 24 '22 at 15:14