Why is my predicate being interpreted as a boolean? (Haskell) - haskell

I’m trying to use the find function on a list of pairs, and I want to find the first pair in which the first element equals x, so I wrote:
find (x == fst) list
Since the fst function lacks an argument, I thought (x == fst) would be a function that takes in a tuple and returns a boolean, but the compiler interprets it as a boolean, as if fst were a variable. Maybe fst is being interpreted as a function? But doesn’t that require it to be surrounded by ()?
I did solve the problem using a list comprehension instead but I’m still curious as how to one would solve it using find.

(==) has type x -> x -> Bool. In your case, type x is (a, b) -> a. This is because one of it's operands is fst, which has that type. Therefore, the type of (==) in your case is ((a, b) -> a) -> ((a, b) -> a) -> Bool. That is, (==) is a function that compares two functions, x and fst.
What you want is to compose fst and (==). For example, (\y -> (x == fst y). This is a function that takes a tuple, y, and checks if x is equal to its first value.
There is a function that composes functions for you, (.). It takes two functions, f(x) and g(x), and returns another function, f(g(x)). You can use this function for your program like this: find ((x ==) . fst) list.
Compare the following programs, the first written as a lambda function, the second with the function composition operator:
(\y -> (x == fst y)
-- Compared to:
(x ==) . fst
Summary:
(==) is comparing two functions, x and fst, and returning a Bool.
What you want instead is a function that takes in a tuple, gets the first item from it, and compares it to x. This can be done with function composition.

If you want to pass a variable into a particular position, use a lambda function:
(\ y -> x == fst y)
Otherwise the compiler has no idea exactly where you're hoping to insert a variable.
If your function calls one function, you can use currying to take a short cut. But for complex expressions, that doesn't work. You can't just leave off the last term in an expression and expect it to work. It only works for a single function.
The other alternative is to take the function (x ==) and the function fst and chain them with the (.) operator:
((x ==) . fst)
It's a matter of personal taste which is "better". (There is no performance difference; the only difference is what your source code looks like.)

Related

How to use groupBy on a list of tuples?

How can I group this list by second element of tuples:
[(3,2),(17,2),(50,3),(64,3)]
to get something like:
[[(3,2),(17,2)],[(50,3),(64,3)]]
I'm actually a newcomer to Haskell...and seems to be falling in love with it. Hope you would help me find an efficient way.
It sounds like you've already identified that you want Data.List.groupBy. The type of this function is
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
So it takes a binary predicate, i.e. an equivalence relation determining how to group elements. You want to group elements by equality on the second term of a pair, so you want
groupBy (\x y -> snd x == snd y) myList
Where snd is a built-in function that gets the second element of a pair.
Incidentally, this pattern of "apply a function to two arguments and then apply a binary function to the results" is very common, especially when calling Data.List functions, so Data.Function provides on.
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
Weird signature, but the use case is just what we want.
((+) `on` f) x y = f x + f y
So your desired groupBy can be written as
groupBy ((==) `on` snd)
Note that groupBy only finds consecutive equal elements. You didn't indicate whether you wanted consecutive equal elements or all equal elements, but if you want the latter, then I don't believe Haskell base provides that function, though you could certainly write it recursively yourself.

How to use Map with more than one operator

is it possible to use map with 2 operators in it like map ((*2)+3) [1,2,3,4]? If is yes how? i want to make a function that apply (x*2)+3 on a list.
You map a single function. But that function can do whatever you want. Your example can be given as an anonymous function for example:
map (\n -> n * 2 + 3) [1,2,3,4]
But you can also use function composition, which is likely more readable for a case like this where your function is a case of "do one thing, then the other":
map ((+3) . (*2)) [1,2,3,4]
This in turn is equal (by the so-called "functor laws") to
map (+3) . map (*2) $ [1,2,3,4]
Which I personally find a little more readable.
I think it is easy to first introduce a lambda expression here:
map (\x -> (x*2)+3) [1,2,3,4]
This will do exactly what you want. You can perform "function composition" with the (.) :: (b -> c) -> (a -> b) -> a -> c function, and thus write this as:
map ((+3) . (*2)) [1,2,3,4]
Here you thus can see it as a "chain" of functions, where we pass the input to the rightmost function (here (*2)), and then the result is passed to the leftmost function (here (+3)).

parenthesis in Haskell functions

I just want to know how do we know which functions need brackets () and which ones do not? For example
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
works fine. But
replicate 100 (product (map (*3) (zipWith (max [1,2,3,4,5] [4,5,6,7,8]))))
does not work. It is because I put a set of brackets for zipWith. In this small example, zipWith and max do not have brackets, but replicate, product and map do. In general is there a way to know/figure out which functions need brackets and which ones dont.
Function application is left associative. So, when you write an expression like:
f g h x
it means:
((f g) h) x
And also the type of zipWith provides a clue:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
it says that zipWith has 3 parameters: a function and two lists.
When you write:
zipWith (max [1,2,3,4,5] [4,5,6,7,8])
The interpreter will understand that
max [1,2,3,4,5] [4,5,6,7,8]
will be the first parameter to zipWith, which is type incorrect. Note that zipWith expects a function of two arguments as its first argument and, as pointed out by #Cubic, max [1,2,3,4,5] [4,5,6,7,8] will return the maximum
between these two lists according the usual lexicographic order, which will be of type [a], for some type a which is instance of Ord and Num. Said that, the error become evident since you are trying to pass a value of type
(Num a, Ord a) => [a]
where a value of type
(a -> b -> c)
is expected.
Rodrigo gave the right answer. I'll just add that it is a misconception to think that some functions need parentheses, while others don't.
This is just like in school math:
3 * (4+5)
It is simply not the case that + expressions need parentheses and * expressions don't need them in general.
In Haskell, you can always get away without parentheses at all. Whenever you need to enclose an expression in parentheses, the alternative is to introduce a local name and bind it to that expression, then use the name instead of the expression.
In your example:
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
let list1 = product list2
list2 = map thrice list3
thrice x = x*3
list3 = zipWith max [1,2,3,4,5] [4,5,6,7,8]
in replicate 100 list1
In fact, I often write functions top down thus:
foo x y z = result
where
result = ...
...
However, as it was said before, expressions that consist of function applications can also often be written without parentheses by making use of (.) and ($) and in such cases, the top down approach from above may be overly verbose and the following would be much clearer (because there is no noise through newly introduced names):
replicate 100
. product
. map (*3)
$ zipWith max [1..5] [4..8]

Haskell, passing a function to filter in one line?

I want to filter everything that is not divisible by 3 from a list in Haskell, this is technically what I want to do
filter (`mod` 3) [1..100]
The problem is, mod x 3 won't return a boolean value. Is there a way to do this in one line? or am I forced to write another function which returns a boolean value? I've read about curried functions, but I'm not sure if its possible to do this because if I used (==) a b and a is a function, it just wouldn't work out.
That is what function composition is for:
filter ((== 0) . (`mod` 3)) [1..100]
As ever, contemplate the types of the involved functions until everything feels natural.
you can use dot notation
filter ((== 0) . (`mod` 3)) [1..100]
this generates
[3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60,63,66,69,72,75,78,81,84,87,90,93,96,99]
The type signature of dot is as follows:
(.) :: (b -> c) -> (a -> b) -> a -> c
If you want to define it in one line and don't want to write another function (which is going to be used in just one place anyway), the easiest way is to define lambda function:
filter (\x -> x `mod` 3 == 0) [1..100]
Point-free style suggested in other answers can sometimes lead to "hard to read" expressions when the auxiliary function is more complex then this. Especially for a beginner.
You can also use a list comprehension:
[x | x <- [1..100], (x `mod` 3) == 0]
An alternative version, using streams:
takeWhile (<=100) $ map (*3) [1..]

Pointfree Composition with Multiple Variables

I've started to wrap my head around it, and rather like using it for simple situations in which I can essentially pipe the values from one output to one input. A simple example of a pointfree composition I'm comfortable with would be:
let joinLines = foldr (++) "" . intersperse "\n"
While playing with GHCI today, I wanted to see if I could compose not and (==) to replicate (/=), but I wasn't really able to reason it out. (==) take two inputs, and not takes one. I thought that this might work:
let ne = not . (==)
With the assumption that the single Bool output of (==) would go to not, but it won't compile, citing the following error:
<interactive>:1:16:
Couldn't match expected type `Bool' with actual type `a0 -> Bool'
Expected type: a0 -> Bool
Actual type: a0 -> a0 -> Bool
In the second argument of `(.)', namely `(==)'
In the expression: not . (==)
I wish I could say it meant much to me, but all I'm getting is that maybe the second argument that's passed to (==) is mucking things up for not? Can anybody help me understand a little better the logic behind this composition?
If you start to remove one argument at the time, you get
ne x y = not (x == y)
= (not . (x ==)) y
ne x = not . (x ==)
= not . ((==) x)
= ((not .) . (==)) x
ne = (not .) . (==)
basically, for every argument you need one (.), properly associated.
The type of (==) is Eq a => a -> a -> Bool. So if you write whatever . (==), and pass a value x to that, you get whatever ((==) x), but (==) x is a function a -> Bool (where a is the type of x, and an instance of Eq). So the whatever must accept arguments of function type.
Another useful operator is (.:), which is a combinator for an initial function taking two arguments:
f . g $ x
f .: g $ x y
Explicit use of curry and uncurry can help switch between "multi-argument" and single-argument functions.
ne = curry (not . uncurry (==))
uncurry "fixes" (==) so that it takes a single argument (x,y) rather than separate x and y arguments. The resulting function can then be composed with not as expected. The composed function, then can be re-curried to accept separate arguments again.
I am not sure if this makes any sense... but it looks readable to me
ne = (.) not . (==)

Resources