Given the following two functions:
minCur a = (\b -> if a > b then b else a)
minCur a b = if a > b then b else a
Asking for the type results for both the same:
minCur :: Ord p => p -> p -> p
How does the User of the function know if he is dealing with a curried function? Does it even matter?
Edit:
Is this currying?
minCur (a,b) = if a > b then b else a
It does not matter, since every function that takes more than one argument is a curried function. In Haskell, every function takes a single parameter and returns a single value (a -> b -> c is the same as a -> (b -> c)).
There shouldn't be a reason for the user to care whether the function is curried or not.
The two function definitions you provided are considered to be the same function. The user shouldn't need to care beyond what the behavior of minCur is and what type it has.
In the case of the version with the tuple, it has a different type. So
min (a, b) = if a > b then b else a
min :: Ord p => (p, p) -> p
And the types (a, a) -> a and a -> a -> a are incompatible. You cannot curry the function with the tuple because it only has one parameter anyway and does not return a function type.
In the libraries, we have a function curry which transforms
f :: (A,B) -> C
f (a,b) = ...
into g = curry f, defined as
g :: A -> B -> C
g a b = ...
We also have the inverse transformation, called uncurry which maps g back into f = uncurry g.
Sometimes, functions like g are called "curried" and functions like f are called "uncurried". This way of speaking is a bit informal since we should instead say, more properly, "g is the curried form of f" and "f is the uncurried form of g".
There is no perfect distinction between "curried" and "uncurried" functions on ther own. For instance, h :: (A,B) -> C -> D can be seen as the currying of h1 :: ((A,B),C) -> D or the uncurrying of h2 :: A -> B -> C -> D, so it would be both curried and uncurred at the same time.
Often, though, we say that a function is curried or not depending on whether it takes a tuple as a single argument or its components as separate arguments. Again, this is a bit informal.
When choosing which style to follow, in Haskell we prefer the curried form since it is easier to apply partially.
Related
Im trying to wrap my head around Haskell and I'm having trouble trying to implement the following signature as a function. Could you guys give me an example using lambda expressions?
(b -> c) -> (a -> b) -> a -> c
Try with simpler examples first. For example,
f :: a -> a
f = ...
Since f is a function of one argument, we can extend this without thinking much into:
f :: a -> a
f = \x -> ...
Picking a return value for this function, we have exactly one good candidate, x, so:
f :: a -> a
f = \x -> x
although we could also have picked undefined or error "meh", or f x, which are less useful.
Here's another simple example:
g :: (a, b) -> (b, a)
g = ...
The only pattern that matches the function's input is a pair, so:
g :: (a, b) -> (b, a)
g = \(x, y) -> ...
This doesn't have to be equivalent to swap, but it's a good candidate because it terminates.
A last example that is more complicated:
h :: ((a, b) -> c) -> a -> b -> c
h = ...
This is a function of three arguments of types (a, b) -> c, a and b, so without thinking much we can extend the answer partially:
h :: ((a, b) -> c) -> a -> b -> c
h = \f -> \x -> \y -> ...
h = \f x y -> ...
(The lower line is just a convenient way to stack curried arguments.)
Now, I gave them names f, x and y because I think f is a good, generic name for a value that contains an ->, and x and y are good, generic names for arbitrary values. I could also have picked a and b to strengthen the connection between the types of the same name, but it'd also be a little confusing. So here, x :: a and y :: b.
As for filling out the function body, I can either go by asking "How do I apply the things I've got so the types align", or I can look at the return type, c, and look at what I have available to make a value of type c. f returns c if I feed it a pair of type (a, b). I have an x :: a and a y :: b, so (x, y) :: (a, b):
h :: ((a, b) -> c) -> a -> b -> c
h = \f x y -> f (x, y)
This is incidentally curry. I don't think you can find any other solution that terminates?
For simple functions there is often only one good candidate. When you have type signatures with multiple values of the same type, you have to consider what happens if you pick one over the other. The first case I can think of is when you implement the >>= operator for the state monad.
Let's rename our type variables:
a becomes oil
b becomes petrol
c becomes co₂
Now, you already recognised what the arguments to your function are:
implementation (x :: petrol -> co₂)
(y :: oil -> petrol)
(z :: oil)
= (? :: co₂)
It's sort of conventional to name functions f, g... and values a, b... _if we know nothing about the underlying types. Ok, but after we named the types, let's pick appropriate names accordingly:
implementation (car :: petrol -> co₂)
(refinery :: oil -> petrol)
(tankship :: oil)
= (? :: co₂)
Or, in lambda form without the local signatures:
implementation = \car refinery tankship -> ?
I'll leave the rest to you.
I can't understand the difference between Dot (function composition) and bind (>>=) .
If I understand, these two ways take the previous result of a function for a new function.
So what is the difference ?
They are pretty different. Let's look at their signatures:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
As you said, the function composition is just a way to pass a result of one function as an argument to another one like this:
f = g . h
is equivalent to
f x = g (h x)
You can think about is as some kind of a "conveyor", where your value goes through several processing steps.
But (>>=) is quite different. It is related to such context as monad which is something like some value in some context (it's highly recommended to read the previous link if you aren't familiar with it).
So let x be some value in a context. Our context will be nullability (Maybe monad), and the value is 2. So, x = Just 2. We could, for example, get it as a result of a lookup from some associative container (such operation might fail, that's the reason why it is Maybe Int, but not Int).
Now we want to pass our x to some arithmetic function f that accepts just Int and may fail, so its signature looks like:
f :: Int -> Maybe Int
We can't just pass our value because of type mismatch. We could unpack x and handle some cases with if, but we could do that in almost all other languages. In haskell, we can use (>>=):
x >>= f
This allows as to chain the effects:
if x is Nothing, then the result is Nothing immediately
else x is unpacked and passed to f
This is a generalization of the operator ?., that you could see in some languages:
x = a?.func1()?.func2();
which checks for null at each "step" and stops immediately if hits null or returns the value in case of success. In haskell it looks like:
x = a >>= func1 >>= func2
However, bind with monads is a much more powerful concept, allowing you, for example, to emulate stateful computations in a language without mutability like haskell.
(>>=) is a form of function application.
(>>=) :: Monad m => m a -> (a -> m b) -> m b
flip ($) :: a -> (a -> b) -> b
It takes a value, but "extracts" part of it in order to apply the given function. Chaining two functions, like x >>= f >>= g requires the argument type of g to be different from (but at the same type similar to) the return type of f, unlike composition, which requires the types to match exactly.
Composed with return, it
really is just function application, but restricted to certain kinds of functions.
flip ($) :: a -> (a -> b) -> b
(>>=) . return :: Monad m => a -> (a -> m b) -> m b
(.) is more like (<=<) (from Control.Monad).
(.) :: (b -> c) -> (a -> b) -> a -> c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
But again, instead of simply passing the result of one function to another, it first "extracts" a value before doing application.
I learn Haskell through reading the "Learn You a Haskell for Great Goog!" book. I want to be sure I correctly understand that is "currying".
I understand a function can't get more then one parameter. When a function has more then one parameter it actually works as a function with one parameter. I.e. this:
func :: Int -> Int -> Int -> Int
works like this (and is the same):
func :: Int -> (Int -> (Int -> Int))
I.e. a function returns a function, that returns a function too, etc. This "nested doll" behaviour is called a "currying" (curried function). First variant of code is like a "syntax sugar".
Any function with more than zero parameter can be partially applied. I.e. it is possible to tell that the "currying" is an action reverse of the "partial application". Am I right?
No.
A reverse of currying is uncurrying.
f :: a -> b -> c
f' :: (a, b) -> c
f' = -- uncurried f
f'' :: a -> b -> c
f'' = -- curried f' = f
A curried function, despite having its "language" arity reduced to 1, keeps the "semantic" arity unchanged (becuse you still have to provide every value for the tuple). The only thing that changes in comparison is the way you pass the arguments.
Partial application is an application that reduces the arity of the function to a number bigger than 0. This is an irreversible operation; you can't unapply arguments.
-- 1 2
f :: a -> b -> c
-- 1
f' :: b -> c
f' = f c -- partially applied f
-- 0 arguments
f'' :: c
f'' = f c1 c2 -- fully applied f
I.e. it is possible to tell that the "currying" is an action reverse of the "partial application".
Almost but the other way around: "Currying" can be seen as the same thing as "partial application".
Let me explain with the help of a ghci session. We start by defining some type synonyms for different kinds of functions.
Prelude> type Binary a b c = (a, b) -> c
Prelude> type Curried a b c = a -> (b -> c)
Prelude> type Unary a b = a -> b
Here, we have two ways to represent a binary function: We have Binary functions like in mathematics, that is, functions that accept a tuple. Then we have Curried functions like usually in Haskell, that is, functions that return a function. And for completeness, we also have a special name for Unary functions.
Now we can use the standard curry and uncurry functions to convert between the two representations of binary functions. In ghci, we can check this as follows:
Prelude> :t curry :: Binary a b c -> Curried a b c
curry :: Binary a b c -> Curried a b c
:: Binary a b c -> Curried a b c
Prelude> :t uncurry :: Curried a b c -> Binary a b c
uncurry :: Curried a b c -> Binary a b c
:: Curried a b c -> Binary a b c
(Note that when you type :t foo :: SomeType, then ghci will check whether foo has type SomeType. If yes, ghci will print it again. If not, ghci will complain).
So as Bartek correctly states in his answer, the inverse of curry is uncurry. But we can also understand the type of curry as follows:
Prelude> :t curry :: Binary a b c -> a -> Unary b c
curry :: Binary a b c -> a -> Unary b c
:: Binary a b c -> a -> Unary b c
If we write the type like this, we see that we can use curry to partially apply a Binary function: Given a f :: Binary a b c and the first argument x :: a we can use curry f x to yield a Unary b c that is still waiting for the second argument of type b.
Having troubles with manually calculating types of given functions in Haskell for an exam at the weekend.
I understand the basics such as:
i x = x :: t -> t
k x y = x :: t -> t1 -> t
But having trouble on more complicated questions such as:
two f x = f (f x)
s x y z = x z (y z)
Any explanations would be much appreciated!
In those two examples the only hints you have as to the types of the functions come from observing the application going on. In Haskell application hardly has any syntax, so I'll rewrite them a bit more obviously.
two f x = f(f(x))
s x y z = x(z)(y(z))
We'll now discover the types of these functions through gradual refinement. For instance, beginning with two we know that it takes in two arguments and thus must have a type which agrees with the (more general) type
two :: a -> b -> c
We also know that the a type variable above actually corresponds to a function because f is being applied to both x and f(x).
two :: (a -> b) -> c -> d
Since f is applied to x we know that here a and c must be the same.
two :: (a -> b) -> a -> d
and since we apply f again to its result f(x) we know that the result type must be the same as the input type
two :: (a -> a) -> a -> b
And finally, the result of calling f is the total result of two so d must also equal a
two :: (a -> a) -> a -> a
This uses all of the information we have in the definition and is the most general type that is compatible with the definition of two.
We can do basically the same process for s. We know it has 3 arguments
s :: a -> b -> c -> d
We know that the first and second arguments are functions of some kind. We see the second argument applied to a single value and the first applied to two values.
s :: (a -> b -> c) -> (d -> e) -> f -> g
We also know that the first input to both functions are the same (namely, it's z each time). This lets us infer that a, d, and f are the same type
s :: (a -> b -> c) -> (a -> d) -> a -> e
We also know that the result of calling the second function is the second argument to the first function, so b and d must be the same.
s :: (a -> b -> c) -> (a -> b) -> a -> e
Finally, the result of fully applying the first function is the final result of s so c and e are the same
s :: (a -> b -> c) -> (a -> b) -> a -> c
While that might be a lot to digest and kind of a blur, the thing to emphasize is that the tools I've used to solve this problem are all primitive. Effectively, I introduce arrows (->) when I see that the type got applied to some values and thus must be a function of a certain number of arguments and I unify type variables by following the values through their expression. These are sufficient tools for inferring the types of simple functions like two and s.
Your two and s are what as known as higher level functions, because they take functions as arguments. You already have the tools to discern their types, you just have to be willing to be a bit more abstract about it.
If you're given the expression
f x
You know the type of f is a -> b with x :: a and f x :: b. If you see
f (f x)
Then you can deduce that the output type of (f x) is the same as the input type for f. This means that a ~ b, so f :: a -> a and x :: a. If we look at the type of two, we can deduce that it follows the pattern
two :: s -> t -> u
but the first argument to two is f, which has the type a -> a, so we can plug that in as
two :: (a -> a) -> t -> u
And x is the second argument with type a, so we can plug that in
two :: (a -> a) -> a -> u
And the return type is the same as the return type of f (f x), which has the return type of f, which has the return type of a, so if we plug that in we get the final type
two :: (a -> a) -> a -> a
For s, we can do similarly. We start off by saying s follows the form
s :: s -> t -> u -> v
since it has 3 arguments. The expression (y z) is function application, so y must have the type y :: a -> b, with z :: a. Plugging that in to s:
s :: s -> (a -> b) -> a -> v
Then we look at x z (y z). Since y z :: b and z :: a, x is a function of two arguments, the first of type a and the second of type b, with some unknown return type c, so we can plug that in as
s :: (a -> b -> c) -> (a -> b) -> a -> c
Let's look at
two f x = f (f x)
We will proceed by writing down what we know, using variables for anything we don't. Some of the things we know will be equations, and like in math, we will substitute around in the equations until we get something that we can't do anything else with.
Starting with the expression f x. f is a function, and its argument type is whatever x's type is, so:
x :: a -- a is a new variable
f :: a -> b -- b is a new variable
These two equations say exactly what I just said in the previous sentence. Also, we created the variable b which is the type of the result of the application:
f x :: b
Now let's move on to f (f x). So the argument type of f has to be the type of f x, which we know is b, so:
f :: b -> c -- c is a new variable
f (f x) :: c
But, of course, a function can only have one type, and we already have a type for f:
f :: a -> b -- from above
That means that
a = b
b = c
We've reached the top level expression now. So now let's look at the types of the input variables we've found together with the expression:
f :: a -> b
x :: a
f (f x) :: c
Now we go substituting around as much as we can, expressing it with as few variables as possible (but only using equalities that we have deduced). We'll try to do it all in terms of a.
f :: a -> b
= a -> a -- because b = a
x :: a
f (f x) :: c
= b -- because c = b
= a -- because b = a
And there we have it:
two :: (a -> a) -> a -> a
^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^
type of f type of x type of result
This is more verbose than necessary, because I repeated myself a lot, so that you could see the reasoning involved. There is a methodical way to do this, but I prefer to do it more like math, going along and discovering what I can. The methodical way usually gets me lost in a sea of variables (which is easy enough for a computer, but hard for my mortal human brain).
I hope this helped.
uncurry f=\(a,b)->f a b
uncurry converts a curried function to a function on pairs, but the function above just converts it to a curried function f a b. Doesn't that contradict the definition of the uncurry function?
What pelotom and Chuck said is 100% right. I think you just got a little confused at some point about curry vs uncurry and function definitions.
We know that a curried function is one like:
add x y = x + y
It's definition would be:
add :: (Num a) => a -> a -> a
Add takes a Num, and returns a function that takes a Num and returns a Num.
By having it this way, we can get a partially applied function, like
add3 = add 3
Thanks to add being curried, when we can pass just one parameter (in this case, 3), we can get back a function that takes a Num and returns a Num.
>add3 5
8
Uncurried functions takes tuples, or grouped together values, like (1,2). (Note, tuples don't have to pairs. You can have a tuple of the form of (1,2,3,4,5). Just regular old uncurry deals with specifically pairs). If we changed our add to be uncurried, it'd be:
add :: (Num t) => (t, t) -> t
add (x, y) = x + y
Which takes a tuple of two Nums and returns a Num. We can't partially apply this like we did with add as a curried function. It needs both parameters, passed in a tuple.
Now, onto the uncurry function! (If you want to know the type of a function, use :t <some function> in GHCi, or use Hoogle).
uncurry :: (a -> b -> c) -> ((a, b) -> c)
uncurry f=\(a,b)->f a b
So what do we know from this? It takes f, which we notice from the definition is a curried function from (a->b->c), and it returns a uncurried function ((a,b)->c).
If we feed uncurry our curried add (remember: add x y), what do we get back?
We get an anonymous function, or lambda function, that takes a tuple, and applies the values of the tuple, a and b, to our function, add.
f a b doesn't mean we get a function -- you'd see a -> if that was the case. We just get the value of f with a and b.
It's kind of like if we did this by hand:
tupleAdd (a,b) = add a b
But uncurry does this all for us, and we can just continue along with our brand new uncurried form of our originally curried function.
Cool, hunh?
Another way of writing this definition so it's clearer what's going on would be:
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f = \(a, b) -> (f a) b
The variable f has type a -> b -> c, i.e. it is a curried function, and uncurry g for some curried function g has the type (a, b) -> c, i.e. an uncurried function.
Remember that when x and y are terms, x y means apply the function x to y. And f a b (or (f a) b) means apply the function f to the argument a, producing a function of type b -> c, then immediately apply this function to b, producing a result of type c. So the right-hand side of this definition is just showing how to unpack the components of a tuple argument and apply them to a curried function, which is exactly the process of uncurrying!
You can write a function which behaves the same way (and with the same signature) without a lambda:
uncurry' :: (a -> b -> c) -> ((a, b) -> c)
uncurry' f (a,b) = f a b
I think this version is easier to read. If you have a tupel and a function which takes two single values (or more exact, which takes one value and returns a function that takes the next value), the uncurry' function does the "unwrapping" of the tuple for us.
Generally if you see something like
f x y z = x + y + z
it's the same as
f = \x y z -> x + y + z
or
f x = \y -> (\z -> x + y + z)
I think you're misreading. It does indeed return a function on pairs. That's what the \(a,b)-> part means — it defines an anonymous function that takes a pair and performs the given function on the values in that pair.