Haskell: beginner function syntax confusion - haskell

I'm currently trying to learn Haskell, but I'm struggling with understanding the syntax. For example, take the map function:
map :: (s -> t) -> [s] -> [t]
map f [] = []
map f (x:xs) = f x : map f xs
I understand what the function does, and that map has a function f :: s -> t as a parameter. But I read map :: (s -> t) -> [s] -> [t] as "map is a function which maps a function mapping from s to t to s and then to t", which is obviously wrong. Could someone clear this up for me?

The type (s -> t) -> [s] -> [t] can be read in two ways. One way is to treat it as a function of two arguments, the first a function of type s -> t and the second a list of type [s]. The return value is of type [t].
The other way is to understand that function arrows are right-associative, so the type is equivalent to (s -> t) -> ([s] -> [t]). Under this interpretation, map is a function that takes a function from element to element s -> t and turns it into a function from list to list [s] -> [t].
Similarly, when using the function, you can think of map foo xs as applying the function map to two arguments foo and xs. Or, since function application is left-associative, you can think of it as (map foo) xs, applying map to the single argument foo to get back a new function which you then apply to xs.
Since Haskell functions are curried, these are just two ways of looking at the exact same thing.

It might be helpful to define a couple type aliases, to make it a bit more explicit what all those arrows and brackets are doing:
type F1 a b = a -> b -- type synonym for single-argument functions
type List a = [a] -- type synonym for lists
so now you can write map's type signature as:
map :: F1 s t -> List s -> List t
which, if you're more familiar with Java or C++ or whatever, looks syntactically a bit more like:
List<T> map(F1<S, T> fun, List<S> list); // applies fun to each element in list
So you can think of it this way: map takes a function and a list, and returns another list. However, since functions are curried in Haskell, you don't have to pass all parameters at once. You could get away with partially applying map to just its first argument. So really its type signature is more like:
F1<List<S>, List<T>> map(F1<S, T> fun); // returns a function that applies fun to each element in a list
... which, when you call map with just that one fun argument, gives you something that sort of looks like:
List<T> mapFun(List<S> list); // applies fun to each element in list
So now back to Haskell: you can read map :: (s -> t) -> [s] -> [t] either as:
"map takes a function from s to t, and a list of s, and returns a list of t"
"map takes a function from s to t, and turns it into a function from a list of s to a list of t"
The former is fine; the latter is more helpful.

How about "map is a function which maps a (function from s to t) over a (list of s) giving a (list of t)"?
That is a direct translation of the type signature into English (albeit not very elegant English).

Read the signature from the end: -> [t] means returns a list of t. The rest is 'regular' parameters.
So, map takes a function that from an s makes a t, and a list of s.
Now it's easy: take a function s->t, apply it to each element of [s] and the result of it is [t].

Related

Access return value

Let's say I have this function:
functionName :: notimportant => a -> ([a])
I would like to recursively call this function and at each call to modify/update the return (the 2 elements from the tuple). The problem is that I do not know how to pattern match the tuple in order to add at each function's call elements in the list(the first parameter of the returned tuple).
I haven't understood your question. If it becomes more coherent, so may this answer.
The canonical code that applies a function like yours recursively is the following:
data Tree a = Node a [a]
unfold :: (a -> [a]) -> a -> Tree a
unfold f x = Node x $ map (unfold f) $ f x
You talk of tuples. I see no tuple in your type signature.

Variable scope in a higher-order lambda function

In working through a solution to the 8 Queens problem, a person used the following line of code:
sameDiag try qs = any (\(colDist,q) -> abs (try - q) == colDist) $ zip [1..] qs
try is an an item; qs is a list of the same items.
Can someone explain how colDist and q in the lambda function get bound to anything?
How did try and q used in the body of lambda function find their way into the same scope?
To the degree this is a Haskell idiom, what problem does this design approach help solve?
The function any is a higher-order function that takes 2 arguments:
the 1st argument is of type a -> Bool, i.e. a function from a to Bool
the 2nd argument is of type [a], i.e. a list of items of type a;
i.e. the 1st argument is a function that takes any element from the list passed as the 2nd argument, and returns a Bool based on that element. (well it can take any values of type a, not just the ones in that list, but it's quite obviously certain that any won't be invoking it with some arbitrary values of a but the ones from the list.)
You can then simplify thinking about the original snippet by doing a slight refactoring:
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f = (\(colDist, q) -> abs (try - q) == colDist)
which can be transformed into
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f (colDist, q) = abs (try - q) == colDist)
which in turn can be transformed into
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f pair = abs (try - q) == colDist) where (colDist, q) = pair
(Note that sameDiag could also have a more general type Integral a => a -> [a] -> Bool rather than the current monomorphic one)
— so how does the pair in f pair = ... get bound to a value? well, simple: it's just a function; whoever calls it must pass along a value for the pair argument. — when calling any with the first argument set to f, it's the invocation of the function any who's doing the calling of f, with individual elements of the list xs passed in as values of the argument pair.
and, since the contents of xs is a list of pairs, it's OK to pass an individual pair from this list to f as f expects it to be just that.
EDIT: a further explanation of any to address the asker's comment:
Is this a fair synthesis? This approach to designing a higher-order function allows the invoking code to change how f behaves AND invoke the higher-order function with a list that requires additional processing prior to being used to invoke f for every element in the list. Encapsulating the list processing (in this case with zip) seems the right thing to do, but is the intent of this additional processing really clear in the original one-liner above?
There's really no additional processing done by any prior to invoking f. There is just very minimalistic bookkeeping in addition to simply iterating through the passed in list xs: invoking f on the elements during the iteration, and immediately breaking the iteration and returning True the first time f returns True for any list element.
Most of the behavior of any is "implicit" though in that it's taken care of by Haskell's lazy evaluation, basic language semantics as well as existing functions, which any is composed of (well at least my version of it below, any' — I haven't taken a look at the built-in Prelude version of any yet but I'm sure it's not much different; just probably more heavily optimised).
In fact, any is simple it's almost trivial to re-implement it with a one liner on a GHCi prompt:
Prelude> let any' f xs = or (map f xs)
let's see now what GHC computes as its type:
Prelude> :t any'
any' :: (a -> Bool) -> [a] -> Bool
— same as the built-in any. So let's give it some trial runs:
Prelude> any' odd [1, 2, 3] -- any odd values in the list?
True
Prelude> any' even [1, 3] -- any even ones?
False
Prelude> let adult = (>=18)
Prelude> any' adult [17, 17, 16, 15, 17, 18]
— see how you can sometimes write code that almost looks like English with higher-order functions?
zip :: [a] -> [b] -> [(a,b)] takes two lists and joins them into pairs, dropping any remaining at the end.
any :: (a -> Bool) -> [a] -> Bool takes a function and a list of as and then returns True if any of the values returned true or not.
So colDist and q are the first and second elements of the pairs in the list made by zip [1..] qs, and they are bound when they are applied to the pair by any.
q is only bound within the body of the lambda function - this is the same as with lambda calculus. Since try was bound before in the function definition, it is still available in this inner scope. If you think of lambda calculus, the term \x.\y.x+y makes sense, despite the x and the y being bound at different times.
As for the design approach, this approach is much cleaner than trying to iterate or recurse through the list manually. It seems quite clear in its intentions to me (with respect to the larger codebase it comes from).

Is Map a function with Two Arguments?

I'm trying to solve a multiple choice question that states the following
map is an overloaded function
map is a polymorphic function
map is a curried function
map is a higher-order function
map is a function with two arguments
I know that map is overloaded, polymorphic, curried and higher-order. Does that mean that map is a function with just a single argument ? (I realize that this is a consequence of a function being curried, and haskell only has functions with single arguments with multiple argument functions being applied through currying and partial application)
Is the reasoning correct ? And if so, how does the map function evaluate a function through partial application ?
Like all Haskell functions, map is a single-argument function. Let's have a look at its type signature:
map :: (a -> b) -> [a] -> [b]
which is equivalent to:
map :: (a -> b) -> ([a] -> [b])
I think this signature is easier to understand in your case: map gets one argument - a function from a to b - and returns another function, this time from [a] to [b].
Essentialy, map "lifts" a function - it takes a regular function and "lifts" it so it'll work on lists. This idea of lifting appears in several places in Haskell.
For example, even is a function from Int to Bool - it takes a number and returns true iff it is even. And map even is a function from [Int] to [Bool] - it takes a list of numbers and returns a list of boolean values. map even is just even working in a different "context" - lists instead of single values.
You can say map takes two argument, but in reality every function in Haskell takes only one argument. Inspect it's type:
λ> :t map
map :: (a -> b) -> [a] -> [b]
So map seems to take two argument according to it's type definition. But since curring takes place in Haskell, you can say that it takes an argument of type (a -> b) and returns [a] -> [b]. And because of currying you can do stuffs like this in which it takes one argument as a parameter and doesn't throw compile error:
λ> let a = map (+ 3)
The point is knowing the difference between how curring makes any function to take one argument and return one argument and understanding the general type definition of any function to see what it takes. Every function in Haskell actually takes only one parameter because of currying.
The original question was taken from https://www.edx.org/course/introduction-functional-programming-delftx-fp101x-0:
Exercise:
Which of the following statements about the Prelude function map :: (a -> b) -> [a] -> [b] is false:
"map is a function with two arguments"
"map is an overloaded function"
...
Actually they agree that "map is an overloaded function" is False, and so "map is a function with two arguments" becomes True.

Understanding Haskell Type Signatures

I am in the process of teaching myself Haskell and I was wondering about the following type signatures:
Prelude> :t ($)
($) :: (a -> b) -> a -> b
Prelude>
How should I interpret (no pun intended) that?
A semi-similar result is also proving to be puzzling:
Prelude> :t map
map :: (a -> b) -> [a] -> [b]
Prelude>
I'll start with map. The map function applies an operation to every element in a list. If I had
add3 :: Int -> Int
add3 x = x + 3
Then I could apply this to a whole list of Ints using map:
> map add3 [1, 2, 3, 4]
[4, 5, 6, 7]
So if you look at the type signature
map :: (a -> b) -> [a] -> [b]
You'll see that the first argument is (a -> b), which is just a function that takes an a and returns a b. The second argument is [a], which is a list of values of type a, and the return type [b], a list of values of type b. So in plain english, the map function applies a function to each element in a list of values, then returns the those values as a list.
This is what makes map a higher order function, it takes a function as an argument and does stuff with it. Another way to look at map is to add some parentheses to the type signature to make it
map :: (a -> b) -> ([a] -> [b])
So you can also think of it as a function that transforms a function from a to b into a function from [a] to [b].
The function ($) has the type
($) :: (a -> b) -> a -> b
And is used like
> add3 $ 1 + 1
5
All it does is take what's to the right, in this case 1 + 1, and passes it to the function on the left, here add3. Why is this important? It has a handy fixity, or operator precedence, that makes it equivalent to
> add3 (1 + 1)
So whatever to the right gets essentially wrapped in parentheses before being passed to the left. This just makes it useful for chaining several functions together:
> add3 $ add3 $ add3 $ add3 $ 1 + 1
is nicer than
> add3 (add3 (add3 (add3 (1 + 1))))
because you don't have to close parentheses.
Well, as said already, $ can be easily understood if you just forget about currying and see it like, say, in C++
template<typename A, typename B>
B dollar(std::function<B(A)> f, A x) {
return f(x);
}
But actually, there is more to this than just applying a function to a value! The apparent similarity between the signatures of $ and map has in fact a pretty deep category-theory meaning: both are examples of the morphism-action of a functor!
In the category Hask that we work with all the time, objects are types. (That is a bit confusionsome, but don't worry). The morphisms are functions.
The most well-known (endo-)functors are those which have an instance of the eponymous type class. But actually, mathematically, a functor is only something that maps both objects to objects and morphisms to morphisms1. map (pun intended, I suppose!) is an example: it takes an object (i.e. type) A and maps it to a type [A]. And, for any two types A and B, it takes a morphism (i.e. function) A -> B, and maps it to the corresponding list-function of type [A] -> [B].
This is just a special case of the functor class signature operation:
fmap :: Functor f => (a->b) -> (f a->f b)
Mathematics doesn't require this fmap to have a name though. And so there can be also the identity functor, which simply assigns any type to itself. And, every morphism to itself:
($) :: (a->b) -> (a->b)
"Identity" exists obviously more generally, you can also map values of any type to themselves.
id :: a -> a
id x = x
And sure enough, a possible implementation is then
($) = id
1Mind, not anything that maps objects and morphisms is a functor... it does need to satisfy the functor laws.
($) is just function application. It gets a function of type a->b, an argument of type a, applies the function and returns a value of type b.
map is a wonderful example for how reading a function type signature helps understanding it. map's first argument is a function that takes a and returns b, and its second argument is a list of type [a].
So map applies a function of type a->b to a list of a values. And the result type is indeed of type [b] - a list of b values!
(a->b)->[a]->[b] can be interpreted as "Accepts a function and a list and returns another list", and also as "Accepts a function of type a->b and returns another function of type [a]->[b]".
When you look at it this way, map "upgrade" f (the term "lift" is often used in this context) to work on lists: if double is a function that doubles an integer, then map double is a function that double every integer in a list.

Creating a list type using functions

For a silly challenge I am trying to implement a list type using as little of the prelude as possible and without using any custom types (the data keyword).
I can construct an modify a list using tuples like so:
import Prelude (Int(..), Num(..), Eq(..))
cons x = (x, ())
prepend x xs = (x, xs)
head (x, _) = x
tail (_, x) = x
at xs n = if n == 0 then xs else at (tail xs) (n-1)
I cannot think of how to write an at (!!) function. Is this even possible in a static language?
If it is possible could you try to nudge me in the right direction without telling me the answer.
There is a standard trick known as Church encoding that makes this easy. Here's a generic example to get you started:
data Foo = A Int Bool | B String
fooValue1 = A 3 False
fooValue2 = B "hello!"
Now, a function that wants to use this piece of data must know what to do with each of the constructors. So, assuming it wants to produce some result of type r, it must at the very least have two functions, one of type Int -> Bool -> r (to handle the A constructor), and the other of type String -> r (to handle the B constructor). In fact, we could write the type that way instead:
type Foo r = (Int -> Bool -> r) -> (String -> r) -> r
You should read the type Foo r here as saying "a function that consumes a Foo and produces an r". The type itself "stores" a Foo inside a closure -- so that it will effectively apply one or the other of its arguments to the value it closed over. Using this idea, we can rewrite fooValue1 and fooValue2:
fooValue1 = \consumeA consumeB -> consumeA 3 False
fooValue2 = \consumeA consumeB -> consumeB "hello!"
Now, let's try applying this trick to real lists (though not using Haskell's fancy syntax sugar).
data List a = Nil | Cons a (List a)
Following the same format as before, consuming a list like this involves either giving a value of type r (in case the constructor was Nil) or telling what to do with an a and another List a, so. At first, this seems problematic, since:
type List a r = (r) -> (a -> List a -> r) -> r
isn't really a good type (it's recursive!). But we can instead demand that we first reduce all the recursive arguments to r first... then we can adjust this type to make something more reasonable.
type List a r = (r) -> (a -> r -> r) -> r
(Again, we should read the type List a r as being "a thing that consumes a list of as and produces an r".)
There's one final trick that's necessary. What we would like to do is to enforce the requirement that the r that our List a r returns is actually constructed from the arguments we pass. That's a little abstract, so let's give an example of a bad value that happens to have type List a r, but which we'd like to rule out.
badList = \consumeNil consumeCons -> False
Now, badList has type List a Bool, but it's not really a function that consumes a list and produces a Bool, since in some sense there's no list being consumed. We can rule this out by demanding that the type work for any r, no matter what the user wants r to be:
type List a = forall r. (r) -> (a -> r -> r) -> r
This enforces the idea that the only way to get an r that gets us off the ground is to use the (user-supplied) consumeNil function. Can you see how to make this same refinement for our original Foo type?
If it is possible could you try and nudge me in the right direction without telling me the answer.
It's possible, in more than one way. But your main problem here is that you've not implemented lists. You've implemented fixed-size vectors whose length is encoded in the type.
Compare the types from adding an element to the head of a list vs. your implementation:
(:) :: a -> [a] -> [a]
prepend :: a -> b -> (a, b)
To construct an equivalent of the built-in list type, you'd need a function like prepend with a type resembling a -> b -> b. And if you want your lists to be parameterized by element type in a straightforward way, you need the type to further resemble a -> f a -> f a.
Is this even possible in a static language?
You're also on to something here, in that the encoding you're using works fine in something like Scheme. Languages with "dynamic" systems can be regarded as having a single static type with implicit conversions and metadata attached, which obviously solves the type mismatch problem in a very extreme way!
I cannot think of how to write an at (!!) function.
Recalling that your "lists" actually encode their length in their type, it should be easy to see why it's difficult to write functions that do anything other than increment/decrement the length. You can actually do this, but it requires elaborate encoding and more advanced type system features. A hint in this direction is that you'll need to use type-level numbers as well. You'd probably enjoy doing this as an exercise as well, but it's much more advanced than encoding lists.
Solution A - nested tuples:
Your lists are really nested tuples - for example, they can hold items of different types, and their type reveals their length.
It is possible to write indexing-like function for nested tuples, but it is ugly, and it won't correspond to Prelude's lists. Something like this:
class List a b where ...
instance List () b where ...
instance List a b => List (b,a) b where ...
Solution B - use data
I recommend using data construct. Tuples are internally something like this:
data (,) a b = Pair a b
so you aren't avoiding data. The division between "custom types" and "primitive types" is rather artificial in Haskell, as opposed to C.
Solution C - use newtype:
If you are fine with newtype but not data:
newtype List a = List (Maybe (a, List a))
Solution D - rank-2-types:
Use rank-2-types:
type List a = forall b. b -> (a -> b -> b) -> b
list :: List Int
list = \n c -> c 1 (c 2 n) -- [1,2]
and write functions for them. I think this is closest to your goal. Google for "Church encoding" if you need more hints.
Let's set aside at, and just think about your first four functions for the moment. You haven't given them type signatures, so let's look at those; they'll make things much clearer. The types are
cons :: a -> (a, ())
prepend :: a -> b -> (a, b)
head :: (a, b) -> a
tail :: (a, b) -> b
Hmmm. Compare these to the types of the corresponding Prelude functions1:
return :: a -> [a]
(:) :: a -> [a] -> [a]
head :: [a] -> a
tail :: [a] -> [a]
The big difference is that, in your code, there's nothing that corresponds to the list type, []. What would such a type be? Well, let's compare, function by function.
cons/return: here, (a,()) corresponds to [a]
prepend/(:): here, both b and (a,b) correspond to [a]
head: here, (a,b) corresponds to [a]
tail: here, (a,b) corresponds to [a]
It's clear, then, that what you're trying to say is that a list is a pair. And prepend indicates that you then expect the tail of the list to be another list. So what would that make the list type? You'd want to write type List a = (a,List a) (although this would leave out (), your empty list, but I'll get to that later), but you can't do this—type synonyms can't be recursive. After all, think about what the type of at/!! would be. In the prelude, you have (!!) :: [a] -> Int -> a. Here, you might try at :: (a,b) -> Int -> a, but this won't work; you have no way to convert a b into an a. So you really ought to have at :: (a,(a,b)) -> Int -> a, but of course this won't work either. You'll never be able to work with the structure of the list (neatly), because you'd need an infinite type. Now, you might argue that your type does stop, because () will finish a list. But then you run into a related problem: now, a length-zero list has type (), a length-one list has type (a,()), a length-two list has type (a,(a,())), etc. This is the problem: there is no single "list type" in your implementation, and so at can't have a well-typed first parameter.
You have hit on something, though; consider the definition of lists:
data List a = []
| a : [a]
Here, [] :: [a], and (:) :: a -> [a] -> [a]. In other words, a list is isomorphic to something which is either a singleton value, or a pair of a value and a list:
newtype List' a = List' (Either () (a,List' a))
You were trying to use the same trick without creating a type, but it's this creation of a new type which allows you to get the recursion. And it's exactly your missing recursion which allows lists to have a single type.
1: On a related note, cons should be called something like singleton, and prepend should be cons, but that's not important right now.
You can implement the datatype List a as a pair (f, n) where f :: Nat -> a and n :: Nat, where n is the length of the list:
type List a = (Int -> a, Int)
Implementing the empty list, the list operations cons, head, tail, and null, and a function convert :: List a -> [a] is left as an easy exercise.
(Disclaimer: stole this from Bird's Introduction to Functional Programming in Haskell.)
Of course, you could represent tuples via functions as well. And then True and False and the natural numbers ...

Resources