I have run these haskell function in ghci then got those output, but i dont know how to explain it. What is the difference between g(x,y) and g(x y) and how the yield that output.
*Main> let j g (x, y) = g(x,y) *Main> :t j j :: ((a, b) -> t) -> (a, b) -> t *Main> let j g (x, y) = g(x y) *Main> :t j j :: (t1 -> t2) -> (t3 -> t1, t3) -> t2
What is the difference between
g(x y)and how the yield that output.
Well Haskell has - compared to the gross of programming languages - an "unusual" syntax (compared to very common languages like C, Java, etc.) how to describe function applications.
f x is a function application with
f the function, and
x the parameter. The brackets are not necessary (in contract to for example programming languages like C, Java, C#, etc.). But can be written, so
f(x) is interpreted as
f (x) and since
(x) is simply
x, the two are equivalent.
With that in mind if we look at
g (x y) we see two function applications:
x y, and
g (x y). In a programming language like Java, this would look like
x are thus both functions (where the "output type" of
x should be the same as the "input type" of
g). We perform function application with
x the function and
y the parameter, and the result is a parameter in a function application with
g the function.
Haskell also has tuples. For example
(4, 2) a 2-tuple.
(x, y) is a 2-tuple as well:
x is the first element, and
y the second. If we thus write
g (x, y), the we perform a function application with
g the function, and
(x, y) (a 2-tuple) the parameter. So that means that
x has type
y has type
g has type
(a, b) -> c.
With that in mind, we can derive the signature of functions, for example:
j g (x, y) = g (x,y)
We see here that
j has "two" parameters (in Haskell all functions have one parameter, the result of that function takes then another parameter), so we start by describing the signature of the function as:
j :: a -> b -> c g :: a (x, y) :: b g (x, y) :: c
(x, y) is a tuple, we specialize the type of
(x, y) as
(d, e), so that means that the signature changes to:
j :: a -> (d, e) -> c g :: a (x, y) :: b ~ (d, e) g (x, y) :: c x :: d y :: e
~ stands for the fact that the two types are the same)
Since we call
(x, y) as parameter, we know that
g is a function. The input type is the type of the parameter
(x, y), so
(d, e), whereas its result type is here the type of the result of
j g (x, y), hence
c, so we derive that
g has type
(d, e) -> c, so that means that:
j :: ((d, e) -> c) -> (d, e) -> c g :: a ~ ((d, e) -> c) (x, y) :: b ~ (d, e) g (x, y) :: c x :: d y :: e
Then all constraints are satisfied, hence the type of
j :: ((d, e) -> c) -> (d, e) -> c
I leave deriving the type of
j g (x, y) = g(x y) as an exercise.