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.
Related
I've created a list of partially applied functions in my REPL like so:
listOfPartiallyAppliedFunctions = map (*) [1..100]
I would then like to create the list of results from completing the function application, which I can easily do by providing a lambda to the map function like so:
let results = map (\x -> x 4) listOfPartiallyAppliedFunctions
Which basically means map the function x applied to 4 over the list of partially applied functions, where x is each partially applied function from the list.
However, I thought it would then follow that I could write:
let results = map (4) listOfPartiallyAppliedFunctions
As there shouldn't be a need to provide a lambda to the map function as it should know to apply 4 to the partially applied functions contained in the listOfPartiallyAppliedFunctions.
However, I am getting this error:
• Non type-variable argument in the constraint: Num ((a -> a) -> b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a b. (Num a, Num ((a -> a) -> b), Enum a) => [b]
Can someone help me parse this error? I thought 4 was an instance of type constructor Num?
However, I thought it would then follow that I could write:
let results = map (4) listOfPartiallyAppliedFunctions
No, if you would have performed \x -> 4 x, you could replace it with 4. But since 4 means it is a Num instance, and you likely did not make a function a -> b an instance of Num, the compiler can not solve this. The compiler thus says that it does not find a way to convert the number 4 into a function, and definitely not a function that takes as input a function Num a => a -> a, and then converts this to a b.
You can however write the above as just:
let results = map ($ 4) listOfPartiallyAppliedFunctions
Here we thus perform a sectioning of an infix operator [Haskell-wiki] on the ($) :: (a -> b) -> a -> b function.
Three "laws" of operator sections are
(a `op` b) = (a `op`) b = (`op` b) a = op a b
(the missing argument goes into the free slot near the operator),
or with $,
a b = (a $ b) = (a $) b = ($ b) a = ($) a b
Thus
(\ x -> x 4) = (\ x -> x $ 4) = (\ x -> ($ 4) x)
and that, by eta-reduction, is
($ 4)
From https://stackoverflow.com/a/57020455/156458
In Haskell, it happens that everything is curried; all functions take just one argument (even uncurried functions in Haskell take a tuple, which is, strictly speaking, a single argument -- you might want to play with the curry and uncurry functions to see how that works).
I am not sure if that is true, but assume so.
If a function takes another function as an argument, is it curried or uncurried in a similar sense as a function taking a tuple or list argument being uncurried? (A pair tuple type is type1 x type2 and can be type1^2, while a function type is type2^{type1}, so I find them similar)
If uncurried, how can I convert such a function to a curried function?
If a function takes another function as an argument, is it curried or uncurried?
It takes just a function, so a single parameter, and hence it is curried. The fact that that parameter is a function is irrelevant.
Such a function is for example map. map has type:
map :: (a -> b) -> ([a] -> [b])
It thus takes a single parameter, a function (of type a -> b), and then returns a function [a] -> [b] that will map a list of as to a list of bs by applying that function.
So map show :: Show a => [a] -> [String] is the result of such function application, and this is again a function.
Yes, the quote is correct. All the talk about "curried" and "uncurried" functions is imprecise jargon.
Haskell is a curried language. Functions in Haskell always have exponential types. If an argument is a tuple, it doesn't matter, it is still just one value (which happens to be a tuple).
The concepts are approximated when we treat an (a,b) -> c Haskell function as the c a * b one. But it's just a mental gymnastics that we do.
What's actually curried or not, are programming languages. For instance, in Lisp,
(lambda (a b) c)
actually has the type c a * b and to turn it into the (c b)a function we need to put it through some transformations.
There actually is no (\a b -> c) lambdas in Haskell, only (\ a -> (\ b -> c)) nested lambdas(*) . When we write (\a b -> c) in Haskell, it is just a syntactical shortcut for (\ a -> (\ b -> c)). It is impossible to have actual (\a b -> c) lambda function in Haskell, though it is approximated by having (\(a,b) -> c) lambda function.
Where you really see the meaning of all this, if when you implement your own language with lambda functions.
Faced with a ((lambda (a b) c) x y z) function call, the real issue is how to pair-up the function's parameters and the values supplied.
Haskell converts it into ((let a=x in (let b=y in c)) z), but Lisp actually pairs up the parameters list (a b) with the list of values (x y z) and reports the length mismatch.
But, being the uncurried language that it is, Lisp is able to have the various twists and tweaks here, like optional arguments, default arguments, named arguments, etc., pairing up the parameters and the values in various different ways -- unlike Haskell, which always pairs up one parameter with one supplied value at a time.
(*) and with another crucial distinction: the a and b in Haskell's (\ a -> (\ b -> c)) are not variables, but patterns. They are not just assigned the values, like in Lisp -- they are matched up with them.
The truth I can see at least, is almost every value in haskell can be seen as a function with, and every function just take one parameter at the time. Let see an example (With Int as example, to be more clear):
f :: Int -> Int -> Int -> Int
f x y z = x + y + z
f can be seen as a function that takes a Int and returns a function
Int -> (Int -> Int)
:t (f 2)
(f 2) :: Int -> Int -> Int
:t (f 2 3)
(f 2 3) :: Int -> Int
(f 2 3) can be seen as a function that takes a Int and returns an Int
finally
:t (f 2 3 4)
(f 2 3 4) :: Int
An example with higher order functions:
h :: (Int -> Int -> Int) -> Int -> Int -> Int
h fn x y = fn x y
A little more complex but just the same idea:
:t (h f)
(h f) :: Int -> Int -> Int -> Int
(h f) is a function, expecting an Int , and returning (Int -> Int -> Int -> Int)
but... wait, was not it expecting to return a function? it should be so
(h f) :: Int -> Int -> (Int -> Int)
well, point made. let's continue
:t (h f 2)
(h f 2) :: Int -> Int -> Int
(h f 2) is a function expecting a Int and returning a function (Int -> Int)
and finally
:t (h f 2 3)
(h f 2 3) :: Int -> Int
(h f 2 3) indeed is a function, expecting a Int, returning an Int
(h f 2 3) 4 == 7
I think the conclusion here is, every function is curried in Haskell.
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.
In this talk at 52:40 this slide below is discussed.
I don't quite understand this definition.
Why is the x needed in the definition ?
Why is the output not needed ?
For example why is the definition not (f . g) x -> y = f (g x) -> y or something like that ?
Is it easier to understand this definition if I look at it as a rewriting rule ? Whenever the expression evaluator encounters a pattern like on the left side it should rewrite it to the right side?
Is the rewriting rule interpretation the only correct way to understand this definition ? (This interpretation is the only way that this definition makes sense to me but I am not even sure if this is the correct way to interpret this definition.) I have to admit that I am quite a beginner in Haskell.
EDIT:
Or this definition is just a sugar for a lambda expression ?
Or the lambda expression is sugar for the rewriting rule ?
Composition can be written in several equivalent ways.
(.) = \f g -> \x -> f (g x)
(.) = \f g x -> f (g x)
f . g = \x -> f (g x)
The last example says "a composition of two functions gives a function, such that..."
More equivalent expressions:
(.) f g = \x -> f (g x)
(.) f g x = f (g x)
(f . g) x = f (g x)
Perhaps the infix notation is confusing you? Let's look at another way to write that definition:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x) -- definition 1
So we can think of (.) as a function which takes three parameters, f (a function), g (another function), and x (a value). It then returns f ( g x). To invoke this function, we could write an expression like:
(.) head tail "test"
which would return 'e'. However, functions with names beginning with certain special characters (like .) can be used infix style, like so:
(head . tail) "test"
Now, another way to define . is like this:
(f . g) x = f (g x) -- definition 2
This is identical to "definition 1", but the notation may look a little strange, with the function "name" . appearing after the first parameter! But this is just another example of infix notation.
Now, let's look at how this function is actually defined in Prelude:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
This is equivalent to definitions 1 and 2, but uses a syntax you may not be familiar with, lambda notation. The right hand side introduces an unnamed function with a single parameter x, and defines that function to be f (g x). So the whole thing says that that the function (.) f g is defined to be that unnamed function! You may wonder why anyone would write this in such a strange way. It will make more sense when you've worked with infix notation and lambdas for a while.
-> is needed for the type definition of the function, i.e to say what types the functions take as arguments and what type has his result. Explanations:
f :: ... is something like "function f has type ...
(a -> b) means the type "a function which takes an argument of type a and returns an argument of type b"
(a -> b) -> (b->c) -> (a->c) means "a function which takes a function of type a->b and a function of type b->c and return a function of type a->c" (this is a simplified formulation. Please refer to the note below)
The second line the the definition of f.g. Its like defining functions in math. There you define a function h by saying what shall be result of h(x) for any given argument x (you can write h(x)=x² for example). You have read the line
(f . g) x = f (g x)
as
(f . g)(x) := f(g(x))
which shall be read as: "The result of the function f . g for any given x shall be f(g(x))"
Conclusion: -> is like the arrow in mathematics, which you might have seen in terms like f : R -> R and = is like := (f(x):=x² means in mathematics, that f(x) is defined to be x²)
Note: The actual type of (a -> b) -> (b->c) -> (a->c) is (as mentioned by #Ben Voigt): "function which takes a function of type a->b and returns a function which maps a function of type b->c onto ta function of type a->c". #jhegedus: Please let me note in the comments if you need explanation for it.
That's not the source code of (.), although it is close. Here's the actual source:
-- | Function composition.
{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
(f . g) is a function. The source uses a lambda form to be that function. A lambda form must provide local bindings for each of its arguments. In this case, there is only one argument, and it is locally bound to the name 'x'. That's why 'x' (which is of type 'a') must be mentioned.
Since it is marked INLINE, it will effectively rewrite the code during the optimizer passes. (IIRC, that's after desugaring (conversion to Core) and before conversion to STG.)
Lambdas are not sugar, they are fundamental. let/where are sugar for lambdas.
Function definitions are almost sugar for lambdas, but the optimizer (in GHC as least) uses the arity in the definition to determine when/how to inline a function. The type "(b -> c) -> (a -> b) -> a -> c" can be thought of as any arity from 0 to 3, and can be defined with any of those arities.
Unnecessary parentheses can be used to strongly hint at the arity you want to use, although the slide does that backwards from the convention I've seen. For example, adding parentheses around "a -> c" to get "(b -> c) -> (a -> b) -> (a -> c)"; that type is generally thought of a binary function type. The slides use that type, but then use a ternary definition.
I'm doing some excersises where I have to add a function's type and explain what it does. I'm stuck with this:
phy = uncurry ($)
The type, according to GHCi is phy :: (a -> b, a) -> b. My haskell knowledge is basic so I really have no idea what it does.
Let's spell out the type part systematically. We'll start with the types of uncurry and ($):
uncurry :: (a -> b -> c) -> (a, b) -> c
($) :: (a -> b) -> a -> b
Since the target expression has ($) as the argument of uncurry, let's line up their types to reflect this:
uncurry :: (a -> b -> c) -> (a, b) -> c
($) :: (a -> b) -> a -> b
The whole type of ($) lines up with the first argument type of uncurry, and the argument and result types of ($) line up with those of uncurry's first argument as shown. This is the correspondence:
uncurry's a <==> ($)'s a -> b
uncurry's b <==> ($)'s a
uncurry's c <==> ($)'s b
This is kinda confusing, because the a and b type variables in one type are not the same as in the other (just like the x in plusTwo x = x + 2 is not the same as the x in timesTwo x = x * 2). But we can rewrite the types to help up reason about this. In simple Haskell type signatures like this, any time you see a type variable you can replace all of its occurrences with any other type get a valid type as well. If you pick fresh type variables (type variables that don't appear anywhere in the original), you get an equivalent type (one that can be converted back to the original); if you pick a non-fresh type you get a specialized version of the original that works with a narrower range of types.
But anyway, let's apply this to the type of uncurry::
-- Substitute a ==> x, b ==> y, c ==> z:
uncurry :: (x -> y -> z) -> (x, y) -> z
Let's redo the "line up" using the rewritten type:
uncurry :: (x -> y -> z) -> (x, y) -> z
($) :: (a -> b) -> a -> b
Now it's obvious: x <==> a -> b, y <==> a and z <==> b. Now, substituting uncurry's type variables for their counterpart types in ($), we get:
uncurry :: ((a -> b) -> a -> b) -> (a -> b, a) -> b
($) :: (a -> b) -> a -> b
And finally:
uncurry ($) :: (a -> b, a) -> b
So that's how you figure out the type. How about what it does? Well, the best way to do that in this case is to look at the type and think about it carefully, figuring out what we'd have to write to get a function of that type. Let's rewrite it this way to make it more mysterious:
mystery :: (a -> b, a) -> b
mystery = ...
Since we know mystery is a function of one argument, we can expand this definition to reflect that:
mystery x = ...
We also know that its argument is a pair, so we can expand a bit more:
mystery (x, y) = ...
Since we know that x is a function and y :: a, I like to use f to mean "function" and to name variables the same as their type—it helps me reason about the functions, so let's do that:
mystery (f, a) = ...
Now, what do we put in the right hand side? We know it must be of type b, but we don't know what type b is (it's actually whatever the caller chooses, so we can't know). So we must somehow make a b using our function f :: a -> b and value a :: a. Aha! We can just call the function with the value:
mystery (f, a) = f a
We wrote this function without looking at uncurry ($), but it turns out that it does the same thing as uncurry ($) does, and we can prove it. Let's start with the definitions of uncurry and ($):
uncurry f (a, b) = f a b
f $ a = f a
Now, substituting equals for equals:
uncurry ($) (f, a) = ($) f a -- definition of uncurry, left to right
= f $ a -- Haskell syntax rule
= f a -- definition of ($), left to right
= mystery (f, a) -- definition of mystery, right to left
So one way to attack a type that you don't understand in Haskell is to just try and write some code that has that type. Haskell is different from other languages in that very often this is a better strategy than trying to read the code.
uncurry :: (a -> b -> c) -> (a, b) -> c
($) :: (a -> b) -> a -> b
uncurry ($) :: (a -> b, a) -> b
If you inspect types of uncurry and $ and its description:
uncurry converts a curried function to a function on pairs.
All it does is it takes a function (a -> b -> c) and returns a function that takes the parameters as a tuple.
So phy does the same thing as $, but instead of f $ x or ($) f x you call it like phy (f, x).
The other two answers are fine. I just have a slightly different take on it.
uncurry :: (a -> b -> c) -> (a, b) -> c
($) :: (a -> b) -> a -> b
Since the "->" in type signatures associates to the right, I can equivalently write these two type signatures like this:
uncurry :: (a -> b -> c) -> ((a, b) -> c)
($) :: (a -> b) -> (a -> b)
uncurry takes an arbitrary function of two inputs and changes it into a funciton of one argument where that argument is a tuple of the original two arguments.
($) takes a simple one-argument function and turns it into...itself. Its only effect is syntactical. f $ is equivalent to f.
(Make sure you understand higher-order functions and currying, read Learn You a Haskell chapter on higher-order functions, then read difference between . (dot) and $ (dollar sign) and function composition (.) and function application ($) idioms)
($) is just a function application, f $ x is equivalent to f x. But that's good, because we can use explicit function application, for example:
map ($2) $ map ($3) [(+), (-), (*), (**)] -- returns [5.0,1.0,6.0,9.0]
which is equivalent to:
map (($2) . ($3)) [(+), (-), (*), (**)] -- returns [5.0,1.0,6.0,9.0]
Check the type of ($): ($) :: (a -> b) -> a -> b. You know that type declarations are right-associative, therfore the type of ($) can also be written as (a -> b) -> (a -> b). Wait a second, what's that? A function that receives an unary function and returns an unary function of the same type? This looks like a particular version of an identity function id :: a -> a. Ok, some types first:
($) :: (a -> b) -> a -> b
id :: a -> a
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry ($) :: (b -> c, b) -> c
uncurry id :: (b -> c, b) -> c
When coding Haskell, always look at types, they give you lots of information before you even look at the code. So, what's a ($)? It's a function of 2 arguments. What's an uncurry? It's a function of 2 arguments too, the first being a function of 2 arguments. So uncurry ($) should typecheck, because 1st argument of uncurry should be a function of 2 arguments, which ($) is. Now try to guess the type of uncurry ($). If ($)'s type is (a -> b) -> a -> b, substitute it for (a -> b -> c): a becomes (a -> b), b becomes a, c becomes b, therefore, uncurry ($) returns a function of type ((a -> b), a) -> b. Or (b -> c, b) -> c as above, which is the same thing. So what does that type tells us? uncurry ($) accepts a tuple (function, value). Now try to guess what's it do from the type alone.
Now, before the answer, an interlude. Haskell is so strongly typed, that it forbids to return a value of a concrete type, if the type declaration has a type variable as a return value type. So if you have a function with a type a -> b, you can't return String. This makes sense, because if your function's type was a -> a and you always returned String, how would user be able to pass a value of any other type? You should either have a type String -> String or have a type a -> a and return a value that depends solely on an input variable. But this restriction also means that it is impossible to write a function for certain types. There is no function with type a -> b, because no one knows, what concrete type should be instead of b. Or [a] -> a, you know that this function can't be total, because user can pass an empty list, and what would the function return in that case? Type a should depend on a type inside the list, but the list has no “inside”, its empty, so you don't know what is the type of elements inside empty list. This restriction allows only for a very narrow elbow room for possible functions under a certain type, and this is why you get so much information about a function's possible behavior just by reading the type.
uncurry ($) returns something of type c, but it's a type variable, not a concrete type, so its value depends on something that is also of type c. And we see from type declaration that the function in the tuple returns values of type c. And the same function asks for a value of type b, which can only be found in the same tuple. There are no concrete types nor typeclasses, so the only thing uncurry ($) can do is to take the snd of a tuple, put it as an argument in function in fst of a tuple, return whatever it returns:
uncurry ($) ((+2), 2) -- 4
uncurry ($) (head, [1,2,3]) -- 1
uncurry ($) (map (+1), [1,2,3]) -- [2,3,4]
There is a cute program djinn that generates Haskell programs based on types. Play with it to see that our type guesses of uncurry ($)'s functionality is correct:
Djinn> f ? a -> a
f :: a -> a
f a = a
Djinn> f ? a -> b
-- f cannot be realized.
Djinn> f ? (b -> c, b) -> c
f :: (b -> c, b) -> c
f (a, b) = a b
This shows, also, that fst and snd are the only functions that can have their respective types:
Djinn> f ? (a, b) -> a
f :: (a, b) -> a
f (a, _) = a
Djinn> f ? (a, b) -> b
f :: (a, b) -> b
f (_, a) = a