This question already has an answer here:
How to filter my list of tuples of two input lists?
(1 answer)
Closed 3 months ago.
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!
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.
Related
I'm pretty good at inferring the type of a lambda expression as long as it does not have any weird functions such as map, filter, foldr or any compositions in it. However, as soon as I have something like
\x y -> map x (y (. x))
I get totally lost and can't for the life of me figure out how to find out the type without using ghci.
Any help would be much appreciated
Thank you
I take it by "weird" you pretty much mean higher order functions. This expression contains two: map :: (a -> b) -> [a] -> [b] and (.) :: (b -> c) -> (a -> b) -> a -> c. It is also a lambda, so likely a higher order function itself. Each parenthesized arrow here is the type of a function parameter.
map reveals that y must return a list of items that x accepts as an argument. So they have the partial signatures x :: _yitem -> _outeritem and y :: _yarg -> [_yitem], where the return value of this map is of type [_outeritem]. Note that we don't know yet how many arrows fit in these wildcards.
(. x) translates to \l -> l . x which translates to \l r -> l (x r). This entire lambda is an argument that fits y, so y is a higher order function. l must accept the return value from x. That has a name, so l :: _outeritem -> _lret, and (. x) :: (_outeritem -> _lret) -> _xarg -> _lret, since r is used as the argument for x. Oh, and _xarg is known because of the map to be _yitem.
Okay, that was a bunch of confusing steps in their own right, so let's line up the results:
type OuterLambda = _xtype -> _ytype -> MapRet
x :: _yitem -> _outeritem
type MapRet = [_outeritem]
y :: YArg -> [_yitem]
type YArg = (_outeritem -> _lret) -> _yitem -> _lret
y :: ((_outeritem -> _lret) -> _yitem -> _lret) -> [_yitem]
Progress! This has names for every type to and from x and y. But our expression is a lambda, so we must accept those two:
(_yitem -> _outeritem) ->
(((_outeritem -> _lret) -> _yitem -> _lret) -> [_yitem]) ->
[_outeritem]
That's one very long type. Let's compare it to the compiler inferred type that Yuji Yamamoto showed us:
(a0 -> b0) ->
(((b0 -> c0) -> a0 -> c0) -> [a0]) ->
[b0]
It matches. We have here quite a few orders of function: the expression expects functions x and y, and y expects a function that itself takes a l function. And all of the types we do have names for may in turn be arbitrarily complex.
Annotating intentionally wrong type (often ()) would help you.
For example:
> (\x y -> map x (y (. x))) :: ()
<interactive>:1:2: error:
• Couldn't match expected type ‘()’
with actual type ‘(a0 -> b0)
-> (((b0 -> c0) -> a0 -> c0) -> [a0]) -> [b0]’
• The lambda expression ‘\ x y -> map x (y (. x))’
has two arguments,
but its type ‘()’ has none
In the expression: (\ x y -> map x (y (. x))) :: ()
In an equation for ‘it’: it = (\ x y -> map x (y (. x))) :: ()
This tip is introduced in this post: http://www.parsonsmatt.org/2018/05/19/ghcid_for_the_win.html
I'm new to Haskell and I have a question about the following code:
a x (b:bs) = a (b x) bs
a x b = x []
What is the general type of these patterns?
With :info a I get: ([t1] -> t) -> [([t1] -> t) -> [t1] -> t] -> t
However, I cannot understand why. Does a have just two "inputs" or not?
I just have two "Inputs" or not?
Yes, you have two parameters (technically one because of the way currying works).
With :info a I get: ([t1] -> t) -> [([t1] -> t) -> [t1] -> t] -> t
This means the first parameter has type [t1] -> t (so it's a function that takes a list of t1s and produces a t), the second parameter has type [([t1] -> t) -> [t1] -> t] (a list of functions that take a function of type [t1] -> t and a list of t1s and produce a t) and the result has type t.
But I cannot understand why.
Let's look at the code:
a x (b:bs) =
The first parameter is just a variable pattern, so its type is anything. The second one is a list pattern, so it must be a list.
So if we use numbered question marks to denote types we don't know yet, we so far know the following:
x :: ?1
b :: ?2
bs :: [?2]
a :: ?1 -> [?2] -> ?3
Now let's look at the body:
a (b x) bs
b is applied to x, so b must be a function that takes the type of x as its parameter. The result of b x is used as the first argument to a, so the result type of b must also match the type of x. Thus ?2 must be ?1 -> ?1 and we get:
x :: ?1
b :: ?1 -> ?1
bs :: [?1 -> ?1]
a :: ?1 -> [?1 -> ?1] -> ?3
Now let's take a look at the second body (b and bs are now no longer in scope, technically there's a new b, but it's not used, so we'll ignore it):
x []
Here x is applied to an empty list. So it must also be a function and its parameter type is some sort of list. Since the result of x [] is also the result of the a, x's result type must be ?3. So we get ?1 = [?4] -> ?3 and thus:
a :: ([?4] -> ?3) -> [([?4] -> ?3) -> ([?4] -> ?3)] -> ?3
Since -> is right-associative, we can get rid of the parentheses at the end there and get:
a :: ([?4] -> ?3) -> [([?4] -> ?3) -> [?4] -> ?3] -> ?3
And now, since that's all the type information we have, all the question marks that are left are actual type variables, so we can replace them with arbitrary type variable names. If we choose ?3 = t and ?4 = t1, we get the exact output of info (but of course we could name them anything else and the type would still be equivalent).
If you only look at the first half of the definition we get a nice type:
a :: t -> [t -> t] -> t1
a x (b:bs) = a (b x) bs
We take a value and apply a bunch of functions from the list to it. We don't know yet what happens after we run out of functions because we haven't looked at the second part yet.
Lets try to imagine another ending first:
a :: t -> [t -> t] -> t
a x [] = x
When we are done we return our final value. Note that this solved our uncertain return type. Since we just do reversed function application over a list we could just fold with reversed function application over the list and get the same function:
a :: t -> [t -> t] -> t
a = foldl (flip ($))
But that isn't how our function ends in reality. It ends with
a x [] = x []
Here is what we just learned: x is a function that takes an list of somethings and returns something. What these somethings are we can't say so lets call them t1 and t2. We know x's type is t so we can just replace all occurrences of t in our first function with [t1] -> t2:
a :: ([t1] -> t2) -> [([t1] -> t2) -> ([t1] -> t2)] -> t2
And that is how that type signature happened! We also know that it is equivalent to:
a x ls = foldl (flip ($)) x ls $ []
which still is a weird function.
I am writing a function called mapper2 that applies a function to two lists:
mapper2 :: (a-> b -> c) -> [a] -> [b] -> [c]
mapper2 f (x:xs) (y:ys) = (f x y) : (mapper2 f xs ys)
mapper2 _ _ _ = []
I am able to compile the function but get an error when I apply it:
*Main> mapper2 (\x -> x*2) [2,4] [4,6]
<interactive>:4:1: error:
• Non type-variable argument in the constraint: Num (b -> c)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall b c. (Num (b -> c), Num b) => [c]
Can someone explain to me how to fix this and what the error means?
Silvio Mayolo has covered the main, practical part of the question, so I will stick to the technical details related to...
what the error means?
To begin with, the error is a bit hairy, but one thing that you can focus on at first is the Num (b -> c) bit. It indicates that you are somehow trying to use a function type (b -> c) as a number (i.e. an instance of Num), which is something that is almost never done intentionally (as we usually do not use functions as numbers). More often than not, when such things happen it is a sign that there is a mismatch in the number of arguments somewhere (which is the case here, as explained by Silvio Mayolo's answer). That said, what follows is an explanation of how the error comes about.
The first argument of mapper2 has type a -> b -> c or, equivalently, a -> (b -> c). When you pass...
(\x -> x * 2) :: Num z => z -> z
... to it, a -> (b -> c) and Num z => z -> z are matched (or, using the jargon, unified), so that the first z becomes a and the second z becomes b -> c. Since both z are supposed to be the same thing, a becomes b -> c as well, and so the type of (\x -> x * 2) is specialised to:
(\x -> x * 2) :: Num (b -> c) => (b -> c) -> (b -> c)
The error message Non type-variable argument in the constraint: Num (b -> c)
refers to how, unlike in e.g. Num x, there is something within the constraint that is not a type variable. In this case, it is function type constructor, ->. While turning on the FlexibleContexts extension, as the error message suggests, would allow that, there is no reason to do so here, as it still wouldn't be what you want (you have no intention of using functions as numbers). Furthermore, doing so in this case would just lead to another type error.
Look at mapper2's type.
mapper2 :: (a -> b -> c) -> [a] -> [b] -> [c]
Now look at the type of the function you're passing in.
(\x -> x * 2) :: Num a => a -> a
The mapper2 function expects a function of two arguments to be passed in, but your lambda only takes one argument.
Hi everyone Haskell newbie here. I'm really confused about how to look at a curried function.
For example, here is a function definition
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
When I call
zipWith' (zipWith' (*)) [[1,2,3],[3,5,6]] [[3,2,2],[3,4,5]]
I understand that
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
is equivalent to
zipWith' :: (a -> b -> c) -> ([a] -> ([b] -> [c]))
But what I don't understand is the way/order to look at it. Should we analyse it from left to right? Such as look at the (a -> b -> c) first and then apply the [a] in to the (a -> b -> c) and lastly apply ([b] -> [c]) into (a -> b -> c) -> [a]? Or is it the other way round?
And if you don't understand what I'm asking (sorry :( ), could you just show me how you think when you see this kind of problems? I freak out whenever I see these functions and it usually takes me a while to figure out :P
Curried functions look scarier than they are. One way of thinking about how they work is uncurrying them. For instance:
(++) :: [t] -> [t] -> [t]
Becomes, when uncurried:
(++) :: ([t], [t]) -> [t]
In my eyes, that's all the explanation needed, but here's a more detailed one, that might explain it fully:
A function of type a -> b takes an argument of type a and returns an argument of type b. Remember that a -> b is in itself a concrete type and could take the place of b in the first, making a function of something like a -> (b -> c).
Let's say that a function f is of type a -> b -> c, which is as above. What does that mean? It is a function that returns a function! That is how currying works. The idea of functions returning other functions allows us to partially apply functions, limiting or specifying their traits.
Let's now make our own function specifying that:
func :: a -> [a] -> [a]
func = \elem -> ( \list -> elem : list )
The lambda expressions here have been written in such a way that it should be obvious what the type means: the first lambda (\elem -> ...) constructs the other based on it's input.
Now, let's have a look at zipWith:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
The first argument to zipWith is a function, which in itself takes two arguments. Not too crazy.
The second argument is a list which can be passed to the function, because of the type variables defined.
The third argument is another list that can be passed to the function after the first.
The return value is a list of the resultant type of the function we passed to zipWith first.
So, let's start with zipping function. It's type is a -> (b -> c). It takes as a parameter of type a, and returns function which transforms b to c. It is isomorphic to it's uncurried equivalence (a, b) -> c, the difference is that we fix first parameter, to get function which now requires only b to return c.
So this is what the zipper's type mean. Now let's move on to zipWith'. It takes as a parameter zipping function (explained above). It returns something of type [a] -> ([b] -> [c]), which is pretty similiar to zipper function. We can say that zipWith' lifts zipping function to work with lists -zipWith' returns a function witch takes a list of as, and returns function which takes list of bs and returns list of cs.
In your example we have zipWith' (*). For simplicity assume that (*) is of type Int -> (Int -> Int) (in reality it is more general - (Num a) => a -> (a -> a). Then we have a ~ b ~ c ~ Int and zipWith' (*) :: [Int] -> ([Int] -> [Int]). Then zipWith' (*) takes as a parameter a list of Ints and returns a function which transforms one list of Ints to another. So it can be used to zip two lists of lists of as. And this is exactly what happens.
In this case it might be helpful to think of the nested lists as (2-dimensional) matrices.
A = ( 1 2 3 ) B = ( 3 2 2 ) --> result = ( 3 4 6 )
( 3 5 6 ) ( 3 4 5 ) ( 9 20 30 )
The outer zip' combines the rows from A and B and the inner zip combines a pair of rows into another row, and so it is clear the result will have the same shape as the inputs.
It also might be helpful to realize that zipWith (*) is just component-wise multiplication of vectors. In fact there is a pattern:
zipWith (*) -- component-wise * on 1-d matrices
zipWith (zipWith (*)) -- component-wise * on 2-d matrices
zipWith (zipWith (zipWith (*))) -- component-wise * on 3-d matrices
...
and of course (*) can be replaced by any binary operation.
Some other list functions and their matrix interpretations:
map - iterate over all of the rows
transpose - transpose rows and columns
concat - flatten the first dimension (i.e. all rows into a single row)
As an exercise you might try implementing matrix multiplication with list operations.
Left to right.
In fact you can see it with 4 different point of view
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
-- take a function, 2 list and returns a list
zipWith (*) :: [a] -> [b] -> [c]
-- new function which takes 2 list and returns a new one
zipWith (*) [1,2,3] :: [b] -> [c]
-- new function which takes a list a produce a new one
zipPwith * [1,2,3] [3,5,6] :: [c]
-- a function without argument, or a value (equivalent in Haskell)
Or right to left :-)
zipPwith * [1,2,3] [3,5,6] :: [c]
-- a function without argument, or a value (equivalent in Haskell)
zipWith (*) [1,2,3] :: [b] -> [c]
-- new function which takes a list a produce a new one
zipWith (*) :: [a] -> [b] -> [c]
-- new function which takes 2 list and returns a new one
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
-- take a function, 2 list and returns a list
I'm asked to write a function "pipeline" which has type [a -> a] -> [a] -> [a], in such a pipeline, each function in the original function list is applied in turn to each element of the input. Eg, pipeline [(+1),(*2),pred] [1,2,3] would return [1,3,5].
The answer from the solution sheet is pipeline = map . foldr (.) id, which I don't quite understand. How can this solution come up?
One way to think about foldr is that
foldr f z xs
replaces every (:) in xs with f and the empty list with z
Note that
[(+1), (*2)]
is shorthand for
(+1) : (*2) : []
You should now be ables to see what
foldr (.) id ((+1) : (*2) : [])
evaluates to. And from this, you will be able to understand the whole expression.
Folds somehow are quite confusing, though they're actually very simple. Especially the right fold: it basically does nothing else but replace each : in a list with some alternative given function, and the list's nil with the init value. For your example:
foldr (.) id [(+1),(*2),pred]
≡ foldr (.) id ( (+1) : (*2) : pred : [] )
≡ (+1) . (*2) . pred . id
so this simply chains all the functions in a list to a big composition.
Once you've got this chain, applying it to all values in another list is trivial, an obvious job for map.
The crux of the problem is having a function of type : [a -> a] -> (a -> a) i.e convert a list of functions to a one function.
foldr has type: (b -> c -> c) -> c -> [b] -> c
Lets see how the type fits:
(b -> c -> c) -> c -> [b] -> c
Replace b with (a -> a) : ((a -> a) -> c -> c) -> c -> [a -> a] -> c
Replace c with (a -> a) : ((a -> a) -> (a -> a) -> (a -> a)) -> (a -> a) -> [a -> a] -> (a -> a)
Type of function (.) is (b -> c) -> (a -> b) -> a -> c, which is what we have in first type in the previous signature, (ours were all a), so we can use (.) there.
For second part i.e (a -> a) we can use id function.
Lets fit these: (.) id and we are left with [a -> a] -> (a -> a) part, which is what we needed
So, foldr (.) id gives us [a -> a] -> (a -> a)
After that the map part is just applying the resulting function of the foldr to each element of list.
NOTE: Use a whiteboard to understand all this till your subconscious get used to do this ;)