Im trying to infer the type of:
((.) foldr)
The type i manually infer differs from the one ghci infer. Here's what i do:
(.) :: ( b -> c) -> (a->b)->a->c
foldr:: (a'->b'->b')->b'->[a']->b'
Now my first doubt. Foldr has to unify with b->c foldr has to unify with (b->c) but there are more than one way to make it happen; like
b ~ (a'->b'->b')
c ~ b'->[a']->b'
or..
b ~ (a'->b'->b')b'->[a']
c ~ b'
How do i know which to take?
Doing different examples in ghci i arrived to the conclusion that haskell tries to unify types in a non greedy fashion for the first argument (This conclusion is totally experimental and can be totally wrong, maybe its the reason i arrive to a wrong type for the function, but is what i thought of the type inferences ive tried on haskell). So, assuming this is true the configuration haskell tries to unify first is:
b ~ (a'->b'->b')
c ~ b'->[a']->b'
So now..
(.)foldr :: (a->b)->a->c
Substituting b and c:
(.)foldr :: (a-> (a'->b'->b') )->a->b'->[a']->b'
Which is close enough the only problem i have are the parentheses in the expression
(a'->b'->b')
Why can i remove them when you cannot remove those in the original foldr, and the function is gonna be an input for foldr. Why after applying the composition functor you can use partial application? Is there a rule for that?
Also i would like if someone coudl confirm or deny the "non greedy" type matching..
The associativity of ->
In Haskell the only type of function is a -> b, which is a function that takes an a and "returns" a b. For this reason a function type of:
a -> b -> c
is implicitly:
a -> (b -> c)
that is a function that takes an a and returns a function that takes a b and returns a c. You just have to remember that -> is right associative. This is the "mechanism" that allows currying.
Answers
How do i know which to take?
So, in your example:
foldr:: (a' -> b' -> b') -> b' -> [a'] -> b'
becomes:
foldr:: (a' -> b' -> b') -> (b' -> ([a'] -> b'))
As you can see the only way to infer a type a -> b is by assigning (a'->b'->b') to a and (b'->([a']->b')) to b.
Why can I remove them when you cannot remove those in the original foldr, and the function is gonna be an input for foldr?
Because after the function composition, the type is:
(a -> (a' -> b' -> b')) -> a -> b' -> [a'] -> b'
-- ^^^^^^^^^^^^^^^^^^^^
Let's focus on the first part:
(a -> (a' -> b' -> b'))
this is, for the right associativity of ->, equal to:
(a -> (a' -> (b' -> b')))
which is also equal to:
(a -> a' -> b' -> b')
for the same associativity rule.
Why after applying the composition functor you can use partial application? Is there a rule for that?
Partial application can be always applied when you have a function taking more than 1 "argument" (or more correctly, when you have a function that returns a function).
In type signature, (->) is right associative, which implies that
a -> b -> c
which is the type of a function that takes an argument of type a and return another function of type b -> c, equals
a -> (b -> c)
However, it does not equals
(a -> b) -> c
which is the type of a function that takes another function of type a -> b as its only argument and return a value of type c.
Question 1:
How do i know which to take?
You should choose first version, as you already did, because
(a'->b'->b')->b'->[a']->b'
equals
(a'->b'->b')->(b'->[a']->b')
And this is called currying, not greedy.
Question 2:
Why can i remove them when you cannot remove those in the original foldr
The same reason.
Related
I am studying for an exam and I'm confused at this function. Based on the output how do I know that the type declaration of the function is (a -> b -> c)? also, how I can evaluate my function?
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
What I understand is that high order functions in haskell mean that they take a function as a parameter and return a function as well, right? how can I call this particular function?
I did this:
zipWith' [1..5] ['a','z','r']
but I know is wrong because I am calling it as if it were the regular zip function that takes 2 lists and returns a tuple. I am just confused at the type declaration
zipWith' :: [a] -> [b] -> [(a,b)]
For this answer, we'll acknowledge that all functions are curried. That is, every function has a type a -> b, where a and b are some type.
A higher-order function is one whose type includes a function for either its argument or return type. Return values are easy: it's any function you ordinary think of as taking more than one argument:
take :: Int -> [a] -> [a]. It takes an Int and returns a (polymorphic) function that takes a list and returns a list.
map :: (a -> b) -> [a] -> [b]. It takes a function (literally any function) and returns a function from lists to lists. The types of the return value is determined by the type of the argument.
Higher-order functions that take an function and return something that isn't a function are actually somewhat rare. Perhaps a commenter will point out an obvious one I am overlooking, but until then, consider fix :: (a -> a) -> a.
Now, zipWith' is an example of a higher-order function whose argument itself must be a higher-order function. The general type a -> b can unify with an ordinary function like ord :: Char -> Int (a ~ Char and b ~ Int) as well as a higher-order function like (+) (with a ~ Num t => t and b ~ Num t => t -> t. The type a -> b -> c will only unify with higher-order functions. a may or may not be a function type, but b -> c is an explicit function type.
This means that once you apply zipWith' to some higher-order function, type inference gives you more information about what the types of [a], [b], and [c] must be in the resulting function.
zipWith' (+) tells you that a ~ b ~ c ~ Num t => [t].
zipWith' (,) tells you that a and b are still unrestricted, but c ~ (a, b)
zipWith' (:) tells you that a is unrestricted, but b ~ c ~ [a].
It may also help if you consider that zip :: [a] -> [b] -> [(a,b)] could be defined as zip = zipWith' (,).
This question already has answers here:
Haskell recursive function example with foldr
(2 answers)
Closed 6 years ago.
module Tf0 where
all' :: (a -> Bool) -> [a] -> Bool
all' p = foldr (&&) True . map p
main :: IO()
xs = [1,3,5,7,9]
xs1 = [1,3,11,4,15]
k1 = all' (<10) xs
k2 = all' (<10) xs1
k3 = all' (<10)
main = print k1
Questions:
In the function definition (all' p = foldr (&&) True . map p) there is no list as an input while the function Type shows a list as an input ([a]), yet trying to check the function (see bellow k1, k2, k3) shows that a list is needed.
How can the function be defined without the list?
One of the fundamental aspects of Haskell is that conceptually a function always takes one argument. Indeed take for instance the function (+):
(+) :: Int -> Int -> Int
(technically it is (+) :: Num a => a -> a -> a, but let us keep things simple).
Now you can argue that (+) takes two arguments, but conceptually it takes one argument. Indeed: the signature is in fact
(+) :: Int -> (Int -> Int)
So you feed it one integer and now it returns a function, for instance:
(+) 5 :: Int -> Int
So you have, by giving it a 5, constructed a function that will add 5 to a given operand (again a function that takes one argument).
Now applying this to your question, the signature of all' is in fact:
all' :: (a -> Bool) -> ([a] -> Bool)
So if you apply all' with one argument, it returns a function that maps a list [a] to a Bool. Say for the sake of argument that we set p to \_ -> True, then we return:
foldr (&&) True . map (\_ -> True) :: [a] -> Bool
so indeed a function that takes a list [a] and maps it on a Bool. In a next phase you apply a list to that (returning) function.
In other words, functional programming can be seen as a long chain of specializing a function further and further until it is fully grounded and can be evaluated.
Haskell only provides this in an elegant way such that you do not have to think about functions generating functions. But conceptually, this happens all the time. Given you want to implement a function f :: a -> b -> c, you can do this like:
f x y = g (x+1) y
(with g :: a -> b -> c), but you can also decide to leave a parameter out, and define it as:
f x = g (x+1)
since g (x+1) will return a function that can apply with the y eventually.
Instead of fmap, which applies a function to a value-in-a-functor:
fmap :: Functor f => (a -> b) -> f a -> f b
I needed a function where the functor has a function and the value is plain:
thing :: Functor f => f (a -> b) -> a -> f b
but I can't find one.
What is this pattern called, where I apply a function-in-a-functor (or in an applicative, or in a monad) to a plain value?
I've implemented it already, I just don't quite understand what I did and why there wasn't already such a function in the standard libraries.
You don't need Applicative for this; Functor will do just fine:
apply f x = fmap ($ x) f
-- or, expanded:
apply f x = fmap (\f' -> f' x) f
Interestingly, apply is actually a generalisation of flip; lambdabot replaces flip with this definition as one of its generalisations of standard Haskell, so that's a possible name, although a confusing one.
By the way, it's often worth trying Hayoo (which searches the entirety of Hackage, unlike Hoogle) to see what names a function is often given, and whether it's in any generic package. Searching for f (a -> b) -> a -> f b, it finds flip (in Data.Functor.Syntax, from the functors package) and ($#) (from the synthesizer package) as possible names. Still, I'd probably just use fmap ($ arg) f at the use site.
As Niklas says, this is application in some applicative functor to a lifted value.
\f a -> f <*> pure a
:: Applicative f => f (a -> b) -> a -> f b
or more generally (?), using Category (.)
\f a -> f . pure a
:: (Applicative (cat a), Category cat) => cat b c -> b -> cat a c
I've noticed that (although I was once told that (a -> a) and a -> a meant the same thing), I get error messages when I use the (a -> a). Should I only use (a -> a) when using brackets amongst the types? (i.e. (5 + 3) instead of 5 + 3)? Just not quite certain of when it's necessary
(a -> a) and a -> a are the same alone,
ff :: (a -> a) -- this compiles
ff = id
gg :: a -> a
gg = id
h :: a -> a -> Bool
h _ _ = True
i = h ff gg -- this compiles => ff & gg are of the same type.
but will be different when combined with more types like:
a -> a -> b
(a -> a) -> b
This is because -> is right-associative, so a -> a -> b actually means a -> (a -> b) (take an a and return a function), which is different from (a -> a) -> b (take a function and return a b).
This is like (1+2)*3 is different from 1+2*3.
Parenthesization disambiguates several constructs in Haskell, when other information available to the compiler doesn't help:
Application associates to the left
so you can omit parens on function arguments.
Expressions involving infix operators are disambiguated by the operator's fixity.
so no need for parens in many cases with binary operators of different fixity.
Consecutive unparenthesized operators with the same precedence must both be either left or right associative to avoid a syntax error.
and finally:
Given an unparenthesized expression x op y op z, parentheses must be added around either x op y or y op z, unless certain conditions about precendence hold
My general advice, if the above statements don't make any sense: over-parenthesize things, until you learn the rules. Or, study the Haskell Report very hard.
Consider the expression 10 / 2 / 5. Is that the same as (10 / 2) / 5 or 10 / (2 / 5)? If you interpret / to be mathematical division, then the former is true, while the latter is false. So you see, the answer to your question is "there is a difference, but only sometimes".
Types are the opposite. a -> b -> c is the same as a -> (b -> c), and definitely not the same as (a -> b) -> c.
You say you're not quite sure when it's necessary: well here it is. When the argument to your function is also a function, then it is necessary.
Consider map :: (a -> b) -> [a] -> [b]. This is different than a -> b -> [a] -> [b], for you see, (a -> b) indicates a specific kind of function: a function from type a to type b.
iterate :: (a -> a) -> a -> [a] is more interesting. This function requires that the input and output types of the function in the first parameter must be the same.
You may be interested in reading up on currying and partial application. One good resource among many: Learn you a Haskell # Curried Functions
This only makes a difference when you're making higher order functions. For example:
f :: a -> a -> b
is a function that expects two arguments of type a and return a value of type b, like so
f 2 2
f True True
But the function
f :: (a -> a) -> b
Expects a function as an argument. The only time where a -> a and (a -> a) are the same if they're the only argument in type inference, like here
f :: (a -> a)
-- Same type as
f :: a -> a
The rules for () in typing are pretty much the same as in normal expressions. It's like expressions a level above.
They are the same. Could you describe the errors you get when you use (a -> a)? It works fine for me with ghci-7.0.3:
Prelude> let f :: (a -> a); f = id
Prelude> f "foo"
"foo"
Prelude>
In general, you need to use parentheses in types when you're using functions as arguments. For example, map :: (a -> b) -> [a] -> [b]. Without the parens, it would mean something else.
A while ago, I asked a question about $, and got useful answers -- in fact, I thought I understood how to use it.
It seems I was wrong :(
This example shows up in a tutorial:
instance Monad [] where
xs >>= f = concat . map f $ xs
I can't for the life of me see why $ was used there; ghci isn't helping me either, as even tests I do there seem to show equivalence with the version that would simply omit the $. Can someone clarify this for me?
The $ is used here because it has lower precedence than normal function application.
Another way to write this code is like so:
instance Monad [] where
xs >>= f = (concat . map f) xs
The idea here is to first construct a function (concat . map f) and then apply it to its argument (xs). As shown, this can also be done by simply putting parenthesis around the first part.
Note that omitting the $ in the original definition is not possible, it will result in a type error. This is because the function composition operator (the .) has a lower precedence than normal function application effectively turning the expression into:
instance Monad [] where
xs >>= f = concat . (map f xs)
Which doesn't make sense, because the second argument to the function composition operator isn't a function at all. Although the following definition does make sense:
instance Monad [] where
xs >>= f = concat (map f xs)
Incidentally, this is also the definition I would prefer, because it seems to me to be a lot clearer.
I'd like to explain why IMHO this is not the used style there:
instance Monad [] where
xs >>= f = concat (map f xs)
concat . map f is an example of so-called pointfree-style writing; where pointfree means "without the point of application". Remember that in maths, in the expression y=f(x), we say that f is applied on the point x. In most cases, you can actually do a final step, replacing:
f x = something $ x
with
f = something
like f = concat . map f, and this is actually pointfree style.
Which is clearer is arguable, but the pointfree style gives a different point of view which is also useful, so sometimes is used even when not exactly needed.
EDIT: I have replaced pointless with pointfree and fixed some examples, after the comment by Alasdair, whom I should thank.
The reason $ is used here is doe to the type signature of (.):
(.) :: (b -> c) -> (a -> c) -> a -> c
Here we have
map f :: [a] -> [[b]]
and
concat :: [[b]] -> [b]
So we end up with
concat . map f :: [a] -> [b]
and the type of (.) could be written as
(.) :: ([[b]] -> [b]) -> ([a] -> [[b]]) -> [a] -> [b]
If we were to use concat . map f xs, we'd see that
map f xs :: [[b]]
And so cannot be used with (.). (the type would have to be (.) :: (a -> b) -> a -> b