In theory I understand what currying is, but in practice i'm puzzled with what I get in ghci.
Let's look at the example below. First here are the types I'll be using.
Prelude> :t f
f :: a -> a -> a -> a
Prelude> :t x
x :: char
Prelude> :t y
y :: char -> char
Prelude> :t z
z :: char -> char -> char
By doing the following, can you explain to me how I get these types?
Prelude> :t f x
f x :: a -> a -> a
Prelude> :t f y
f y :: (char -> char) -> (char -> char) -> char -> char
Prelude> :t f z
f z
:: (char -> char -> char)
-> (char -> char -> char) -> char -> char -> char
Note: the
char
as type parameter, is not aChar
acter. Since it starts with a lowercase, it is a type parameter. The type ofx
is thusx :: b
as well.
A function in Haskell has exactly one parameter. If one writes:
f :: a -> a -> a -> a
then this is actually short for:
f :: a -> (a -> (a -> a))
So f
takes a parameter of type a
, and returns a function of type a -> (a -> a)
.
f x :: a -> a -> a
In case we want to derive the type of f x
, we can see that:
f :: a -> (a -> (a -> a))
x :: b
since x
is the parameter of a function application with f
as function, it thus means that the type of x
(b
) should be the same as the type of the parameter of the function (a
). So it means that a ~ b
(a
is the same type as b
).
The type of the result the type of the output of the function, so a -> (a -> a)
, or b -> (b -> b)
. But since b
is not more specific than a
, both are fine.
A less verbose expression of a -> (a -> a)
is a -> a -> a
.
f y :: (b -> b) -> (b -> b) -> b -> b
So what about f y
? As ingredients, we have:
f :: a -> (a -> (a -> a))
y :: b -> b
Since y
is the parameter of a function application with f
, the type of y
(b -> b
) is the same type as a
, so that means that a ~ (b -> b)
.
The type of output is thus:
f y :: a -> (a -> a)
or when we convert this:
f y :: (b -> b) -> ((b -> b) -> (b -> b))
or less verbose:
f y :: (b -> b) -> (b -> b) -> b -> b
f z :: (b -> b -> b) -> (b -> b -> b) -> b -> b -> b
As ingredients we have:
f :: a -> (a -> (a -> a))
z :: b -> (b -> b)
So that means that for a function application f z
, we thus have a ~ (b -> (b -> b))
. The result is that the type of f z
is:
f z :: a -> (a -> a)
or when we convert a
to (b -> (b -> b))
:
f z :: (b -> (b -> b)) -> ((b -> (b -> b)) -> (b -> (b -> b)))
or less verbose:
f z :: (b -> b -> b) -> (b -> b -> b) -> b -> b -> b
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments