How does the “fst filter” work if the filter is to get a function that returns a Bool-Type and fst just returns the first element of the tuple?
In a way, you answered your question! Let me break it:
the filter should get a function that returns a Bool type
Ok, let's see what you pass: fst . fst function? Yes, it is, therefore, we have the first part. Does he return a Bool ? Well, let's see what he does:
fst returns only the first element of the tuple
So, if the first element of the tuple is Bool , then yes, it returns bool! If the first element of the tuple is something other than Bool , it does not execute and will not output typecheck.
Let's take another look at the types that you put. I am going to change the names of type variables to make everything clearer:
filter :: (a -> Bool) -> [a] -> [a] fst :: (b, c) -> b
fst takes (b, c) and returns b , and the filter expects a function that takes a and returns a Bool . We go through fst , so the above should be (b, c) as the first parameter of fst . The return value of the function we pass to filter should be Bool , so b above should be Bool . And c can be anything, because it is not used by the filter at all. Substituting the values for a and b , we get the final type for filter fst of:
filter fst :: [(Bool, c)] -> [(Bool, c)]
Finally, the map type:
map :: (d -> e) -> [d] -> [e]
(Again, I renamed the type variables here, just to distinguish them from the ones we used above, but remember that it doesn't really matter what they are called if they are consistent within the scope of the type annotation)
map (filter fst) passes filter fst , which we defined above as the first map parameter. Substituting the parameter for d and the result for e , we can see that this function should be [(Bool, c)] -> [(Bool, c)] , in other words, both d and e are (Bool, c) . Inserting them into the function, we get the final type:
map (filter fst) :: [[(Bool, c)]] -> [[(Bool, c)]]