For Haskell type signature, like babel :: a -> b -> c, is c the return type? - haskell

why doesn't Haskell use some kind of special format to reflect this, or -> c can be understood in another way?

You can look at babel’s type signature in two ways.
(1) babel takes two inputs of type a and b; it produces an output of type c.
(2) babel takes an input of type a and produces an output of type (b -> c).
(1) gives you back a value of type c with babel fully applied. (2) gives you back a intermediate function of type (b -> c) with babel partially applied; if you choose to apply the intermediate function to a value of type b, you then get the result as you would get from case (1).
This ability to choose partially or fully apply a function gives you the power to build complex functions by gluing simple (intermediate) functions together.
why doesn't Haskell use some kind of special format to reflect this…?
By default, all functions in Haskell take one input; a function of two arguments is just a function that returns a function. Currying by default is already clear in the type signature. This is why (->) associates to the right so we don't have to write babel :: a -> (b -> c)

Haskell uses a concept called currying, which means there are only single parameter functions, and multiple parameter functions are just functions returning another functions, with the previous parameter "baked in", until all the parameters are filled in.
so
add :: Int -> Int -> Int
add x y = x + y
is equivalent to
add :: Int -> (Int -> Int)
add = \x -> \y -> x + y

You can think of a function like babel :: a -> b -> c as a pipeline.
It's a function that takes an a, then returns a function that takes a b, which then returns a c. Partial application is what makes this work, any application returns something, either a function or the last value c.

Related

A Haskell function is higher order if and only if its type has more than one arrow?

A professor teaching a class I am attending claimed the following.
A higher-order function could have only one arrow when checking its type.
I don't agree with this statement I tried to prove it is wrong. I tried to set up some function but then I found that my functions probably aren't higher-order functions. Here is what I have:
f x y z = x + y + z
f :: a -> a-> a -> a
g = f 3
g :: a -> a -> a
h = g 5
h :: a -> a
At the end of the day, I think my proof was wrong, but I am still not convinced that higher-order functions can only have more than one arrow when checking the type.
So, is there any resource or perhaps someone could prove that higher-order function may have only one arrow?
Strictly speaking, the statement is correct. This is because the usual definition of the term "higher-order function", taken here from Wikipedia, is a function that does one or both of the following:
takes a function as an argument, or
returns a function as its result
It is clear then that no function with a single arrow in its type signature can be a higher-order function, because in a signature a -> b, there is no "room" to create something of the form x -> y on either side of an arrow - there simply aren't enough arrows.
(This argument actually has a significant flaw, which you may have spotted, and which I'll address below. But it's probably true "in spirit" for what your professor meant.)
The converse is also, strictly speaking, true in Haskell - although not in most other languages. The distinguishing feature of Haskell here is that functions are curried. For example, a function like (+), whose signature is:
a -> a -> a
(with a Num a constraint that I'll ignore because it could just confuse the issue if we're supposed to be counting "arrows"), is usually thought of as being a function of two arguments: it takes 2 as and produces another a. In most languages, which all of course have an analagous function/operator, this would never be described as a higher-order function. But in Haskell, because functions are curried, the above signature is really just a shorthand for the parenthesised version:
a -> (a -> a)
which clearly is a higher-order function. It takes an a and produces a function of type a -> a. (Recall, from above, that returning a function is one of the things that characterises a HOF.) In Haskell, as I said, these two signatures are one and the same thing. (+) really is a higher-order function - we just often don't notice that because we intend to feed it two arguments, by which we really mean to feed it one argument, result in a function, then feed that function the second argument. Thanks to Haskell's convenient, parenthesis-free, syntax for applying functions to arguments, there isn't really any distinction. (This again contrasts from non-functional languages: the addition "function" there always takes exactly 2 arguments, and only giving it one will usually be an error. If the language has first-class functions, you can indeed define the curried form, for example this in Python:
def curried_add(x):
return lambda y: x + y
but this is clearly a different function from the straightforward function of two arguments that you would normally use, and usually less convenient to apply because you need to call it as curried_add(x)(y) rather than just say add(x,y).
So, if we take currying into account, the statement of your professor is strictly true.
Well, with the following exception, which I alluded to above. I've been assuming that something with a signature of the form
a -> b
is not a HOF*. That of course doesn't apply if a or b is a function. Often, that function's type will include an arrow, and we're tacitly assuming here that neither a or b contains arrows. Well, Haskell has type synonyms, so we could easily define, say:
type MyFunctionType = Int -> Int
and then a function with signature MyFunctionType -> a or a -> MyFunctionType is most certainly a HOF, even though it doesn't "look like one" from just a glance at the signature.
*To be clear here,a and b refer to specific types which are as yet unspecified - I am not referring to an actual signature a -> b which would mean a polymorphic function that applies to any types a and b, which would not necessarily be functions.
Your functions are higher order. Indeed, take for example your function:
f :: a -> a -> a -> a
f x y z = x + y + z
This is a less verbose form of:
f :: a -> (a -> (a -> a))
So it is a function that takes an a and returns a function. A higher order function is a function that (a) takes a function as parameter, or (b) returns a function. Both can be true at the same time. Here your function f returns a function.
A function thus always has type a -> b with a the input type, and b the return type. In case a has an arrow (like (c -> d) -> b), then it is a higher order function, since it takes a function as parameter.
If b has an arrow, like a -> (c -> d), then this is a higher order function as well, since it returns a function.
Yes, as Haskell functions are curried always, I can come up with minimal examples of higher order functions and examples:
1) Functions that takes a function at least as parameter, such as:
apply :: (a -> b) -> a -> b
apply f x = f x
2) at least 3 arguments:
sum3 :: Int -> Int -> Int
sum3 a b c = a + b + c
so that can be read as:
sum3 :: Int -> (Int -> Int)

Haskell currying explanation needed

I'm trying to understand the concept of currying and went to the Haskell documentation. However, it says that
f is the curried form of g
Yet f takes two arguments and g only one. Since currying is converting a function which takes multiple arguments to a function which takes one argument and returns another function, shouldn't 'g' be the curried function?
From the haskell documentation
Currying is the process of transforming a function that takes multiple arguments into a function that takes just a single argument and returns another function if any arguments are still needed.
f :: a -> b -> c
is the curried form of
g :: (a, b) -> c
So this does seem contradictory to me and I also don't see any of these 2 functions return a function either.
Yet f takes two arguments and g only one.
No, in fact both functions take one parameter. In fact in Haskell all functions take exactly one parameter.
If you write a signature like:
f :: a -> b -> c
then this is a less verbose form of:
f :: a -> (b -> c)
How does that work? f is a function that takes one parameter, and then returns another function that again takes a parameter.
So take for example a function add :: Int -> Int -> Int.
If we write add 5 2, we thus calculate 5 + 2. It looks like it takes two parameters, but in fact we have written (add 5) 2. We thus call the add function with 5 as parameter. This returns a function (let us call this function add5 :: Int -> Int). So this add5 function adds 5 to a number. So if we then call add5 2, then we obtain 7, since add5 returns 5 added to the parameter.
We can however construct a function (like g) that takes one parameter that is a 2-tuple, so we can use another type to pass two values as one parameter. In fact you can see g(5, 2) is actually g (5, 2): you call the function with one parameter, a 2-tuple (5, 2).
So the currying aims to transform such g function that takes one parameter (a 2-tuple) into a function f that takes again one parameter, and this will then construct a function that will take the second element of the original 2-tuple.
The type a -> b -> c is actually a -> (b -> c).
So f doesn't take two arguments, of type a and a b and return c, it takes one argument of type a, and returns b -> c, a function from b to c.

Understanding Data.Function.on type signature

I'm still a beginner when it comes to Haskell syntax and functional programming languages so when I look at the type declaration for Data.Function.on which is on :: (b -> b -> c) -> (a -> b) -> a -> a -> c, my interpretation is that it takes four parameters: (b -> b -> c), (a -> b), a, a, and returns c. However, when I look at the general use syntax for Data.Function.on which is (*) `on` f = \x y -> f x * f y, it is only taking two function parameters, not four, so how does the type signature relate to the usage syntax?
my interpretation is that it takes four parameters
All Haskell functions take one argument. Some of them just return other functions.
The best way to look at the signature for on is as a higher-order function: (b -> b -> c) -> (a -> b) -> (a -> a -> c). This says "if you give me a binary operator that takes bs and gives a c and a way to get bs from as, I will give you a binary operator that takes as and gives a c". You can see this in the definition:
(*) `on` f = \x y -> f x * f y
The Haskell arrow for function types hides a simple but clever idea. You have to think of -> as an operator, like + and -, but for types. It takes two types as arguments and gives you a new type consisting of a function. So in
Int -> String
You have the types Int and String, and you get a function from an Int to a String.
Just like any other operator, you need a rule for a chain of them. If you think of -, what does this mean?
10 - 6 - 4
Does it mean (10 - 6) - 4 = 0, or does it mean 10 - (6 - 4) = 8? The answer is the first one, which is why we say that - is "left associative".
The -> operator is right associative, so
foo :: Int -> String -> String
actually means
foo :: Int -> (String -> String)
Think about what this means. It means that foo doesn't take 2 arguments and return a result of type String, it actually takes 1 argument (the Int) and returns a new function that takes the second argument (the String) and returns the final String.
Function application works the same way, except that is left associative. So
foo 15 "wibble"
actually means
(foo 15) "wibble"
So foo is applied to 15 and returns a new function which is then applied to "wibble".
This leads to a neat trick: instead of having to provide all the parameters when you call a function (as you do in just about every other programming language), you can just provide the first one or the first few, and get back a new function that expects the rest of the parameters.
This is what is happening with on. I'll use a more concrete version where 'f' is replaced by 'length'.
(*) on length
you give on its first two parameters. The result is a new function that expects the other two. In types,
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
In this case (*) has type Num n => n -> n -> n (I'm using different letters to make this less confusing), so that is matched with the type of the first argument to on, leading to the conclusion that if type b is substitued by n then type c must be as well, and and must also be a Num instance. Therefore length must return some numeric type. As it happens the type of length is [d] -> Int, and Int is an instance of Num, so that works out. So at the end of this you get:
(*) `on` length :: [d] -> [d] -> Int
As an intuitive aid, I read this as "if you give me a comparator of type b, and a way to extract values of type b from values of type a, I will give you a comparator of type a".
E.g. if a is some composite data type and b is some numerical attribute of these data values, you can express the idea of sorting these composite data types by using Data.Function.on.

Usefulness of "function arrows associate to the right"?

Reading http://www.seas.upenn.edu/~cis194/spring13/lectures/04-higher-order.html it states
In particular, note that function arrows associate to the right, that
is, W -> X -> Y -> Z is equivalent to W -> (X -> (Y -> Z)). We can
always add or remove parentheses around the rightmost top-level arrow
in a type.
Function arrows associate to the right but as function application associates to the left then what is usefulness of this information ? I feel I'm not understanding something as to me it is a meaningless point that function arrows associate to the right. As function application always associates to the left then this the only associativity I should be concerned with ?
Function arrows associate to the right but [...] what is usefulness of this information?
If you see a type signature like, for example, f : String -> Int -> Bool you need to know the associativity of the function arrow to understand what the type of f really is:
if the arrow associates to the left, then the type means (String -> Int) -> Bool, that is, f takes a function as argument and returns a boolean.
if the arrow associates to the right, then the type means String -> (Int -> Bool), that is, f takes a string as argument and returns a function.
That's a big difference, and if you want to use f, you need to know which one it is. Since the function arrow associates to the right, you know that it has to be the second option: f takes a string and returns a function.
Function arrows associate to the right [...] function application associates to the left
These two choices work well together. For example, we can call the f from above as f "answer" 42 which really means (f "answer") 42. So we are passing the string "answer" to f which returns a function. And then we're passing the number 42 to that function, which returns a boolean. In effect, we're almost using f as a function with two arguments.
This is the standard way of writing functions with two (or more) arguments in Haskell, so it is a very common use case. Because of the associativity of function application and of the function arrow, we can write this common use case without parentheses.
When defining a two-argument curried function, we usually write something like this:
f :: a -> b -> c
f x y = ...
If the arrow did not associate to the right, the above type would instead have to be spelled out as a -> (b -> c). So the usefulness of ->'s associativity is that it saves us from writing too many parentheses when declaring function types.
If an operator # is 'right associative', it means this:
a # b # c # d = a # (b # (c # d))
... for any number of arguments. It behaves like foldr
This means that:
a -> b -> c -> d = a -> (b -> (c -> d))
Note: a -> (b -> (c -> d)) =/= ((a -> b) -> c) -> d ! This is very important.
What this tells us is that, say, foldr:
λ> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
Takes a function of type (a -> b -> b), and then returns... a function that takes a b, and then returns... a function that takes a [a], and then returns... a b. This means that we can apply functions like this
f a b c
because
f a b c = ((f a) b) c
and f will return two functions each time an argument is given.
Essentially, this isn't very useful as such, but is important information for when we want to interpret and call function types.
However, in functions like (++), associativity matters. If (++) were left associative, it would be very slow, so it's right associative.
Early functional language Lisp suffered from excessively nested parenthesis (which make code (or even text (if you do not mind to consider a broader context)) difficult to read. With time functional language designers opted to make functional code easy to read and write for pros even at cost of confusing rookies with less uniform rules.
In functional code,
function type declaration like (String -> Int) -> Bool are much more rare than functions like String -> (Int -> Bool), because functions that return functions are trade mark of functional style. Thus associating arrows to right helps reduce parentheses number (on overage, you might need to map a function to a primitive type). For function applications it is vise-versa.
The main purposes is convenience, because partial function application goes from left to right.
Every time you partially apply a function to a set of values, the remaining type has to be valid.
You can think of arrow types as a queue of types, where the queue itself is a type. During partial function application, you dequeue as many types from the queue as the number of arguments, yielding whatever remains of the queue. The resulting queue is still a valid type.
This is why types associate to the right. If types associate to the left, it will behave like a stack, and you won't be able to partially apply it the same way without leaving "holes" or undefined domains. For instance, say you have the following function:
foo :: a -> b -> c -> d
If Haskell types were left-associative, then passing a single parameter to foo would yield the following invalid type:
((? -> b) -> c) -> d
You will then be forced to circumvent it by adding parentheses, which could hamper readability.

How to define a function inside haskell newtype?

I am trying to decipher the record syntax in haskell for newtype and my understanding breaks when there is a function inside newtype. Consider this simple example
newtype C a b = C { getC :: (a -> b) -> a }
As per my reasoning C is a type which accepts a function and a parameter in it's constructor.
so,
let d1 = C $ (2 *) 3
:t d1 also gives
d1 :: Num ((a -> b) -> a) => C a b
Again to check this I do :t getC d1, which shows this
getC d1 :: Num ((a -> b) -> a) => (a -> b) -> a
Why the error if I try getC d1? getC should return the function and it's parameter or at least apply the parameter.
I can't have newtype C a b = C { getC :: (a->b)->b } deriving (Show), because this won't make sense!
It's always good to emphasise that Haskell has two completely separate namespaces, the type language and the value language. In your case, there's
A type constructor C :: Type -> Type -> Type, which lives in the type language. It takes two types a, b (of kind Type) and maps them to a type C a b (also of kind Type)†.
A value constructor C :: ((a->b) -> a) -> C a b, which lives in the value language. It takes a function f (of type (a->b) -> a) and maps it to a value C f (of type C a b).
Perhaps it would be less confusing if you had
newtype CT a b = CV ((a->b) -> a)
but because for a newtype there is always exactly one value constructor (and exactly one type constructor) it makes sense to name them the same.
CV is a value constructor that accepts one function, full stop. That function will have signature (a->b) -> a, i.e. its argument is also a function, but as far as CT is concerned this doesn't really matter.
Really, it's kind of wrong that data and newtype declarations use a = symbol, because it doesn't mean the things on the left and right are “the same” – can't, because they don't even belong to the same language. There's an alternative syntax which expresses the relation better:
{-# LANGUAGE GADTs #-}
import Data.Kind
data CT :: Type -> Type -> Type where
CV :: ((a->b) -> a) -> CT a b
As for that value you tried to construct
let d1 = CV $ (\x->(2*x)) 3
here you did not pass “a function and a parameter” to CV. What you actually did‡ was, you applied the function \x->2*x to the value 3 (might as well have written 6) and passed that number to CV. But as I said, CV expects a function. What then happens is, GHC tries to interpret 6 as a function, which gives the bogus constraint Num ((a->b) -> a). What that means is: “if (a->b)->a is a number type, then...”. Of course it isn't a number type, so the rest doesn't make sense either.
†It may seem redundant to talk of “types of kind Type”. Actually, when talking about “types” we often mean “entities in the type-level language”. These have kinds (“type-level types”) of which Type (the kind of (lifted) value-level values) is the most prominent, but not the only one – you can also have type-level numbers and type-level functions – C is indeed one.Note that Type was historically written *, but this notation is deprecated because it's inconsistent (confusion with multiplication operator).
‡This is because $ has the lowest precedence, i.e. the expression CV $ (\x->(2*x)) 3 is actually parsed as CV ((\x->(2*x)) 3), or equivalently let y = 2*3 in CV y.
As per my reasoning C is a type which accepts a function and a parameter
How so? The constructor has only one argument.
Newtypes always have a single constructor with exactly one argument.
The type C, otoh, has two type parameters. But that has nothing to do with the number of arguments you can apply to the constructor.

Resources