Haskell: Explanation of function syntax - haskell

In this custom made version of the map function, there is an "f" is a few spots. I'm not sure what the f means in the function (I'm a beginner in Haskell). Is it something to do with higher order functions? Can someone explain what f means and then explain what the actual function is doing to create the map functionality?
map f [] = []
map f (a:b) = f a:map f b

f is a function that is a parameter of the map function since map has the following type:
map :: (a -> b) -> [a] -> [b]
That it is, a function from a to b and a list of elements of type a and then using the function passed as the first parameter to convert the list (passed as second parameter) in a list of element of type b by using the function (passed as first parameter)
This function is very useful for traversing a list applying a function.
Let's say I have a list of numbers
For example:
[2,3,4,5]
If i want to add 1 to each element of the list I could use map as following:
map (+1) [2,3,4,5]
Or if you prefer the lambda use:
map (\x -> x+1) [2,3,4,5]
And we'll get as an answer:
[3,4,5,6]
So in the implementation of map
map f [] = []
map f (a:b) = f a:map f b
We can see that the f is this function that is used to transform the list by applying it to each element of the list
The implementation is recursive goes until the end of the list converting element by element and appending them to the list so the list has the same order as before the function was applied.

In your map definition, f is the first argument you're supplying to it. Your first pattern match could also be defined with a lambda to denote where the parameter is coming from:
map f [] = -- ...
map \f -> \[] -> -- ...
In the second definition, you're recursing down the contents of the (:) pattern match:
map f (x:xs) = (f x) : (map f xs)
I'm applying f to the first element we see x, then prepending that result to the recursed call of map through the rest of xs.

Related

Haskell Functions (map,foldr, foldl)

I am struggling to think of a way to utilize these functions for this beginner level coding class that I am taking to learn functional programming in Haskell. The functions I have to write are shown below, asum is supposed to turn a list of integers [a1,a2,..,an] into the alternating sum a1-a2+a3-a4+.… and I am not sure how to approach it with these functions. The xor function is supposed to that computes the XOR of a list of Booleans. I need some help to understand how to use these functions and it would greatly appreciated. I am also new to Haskell so any explanations would help. Thanks I have to use map foldr foldl.
asum :: (Num a) => [a] -> a
xor :: [Bool] -> Bool
I would say start by running the following, one by one, in GHCi:
:t foldr
:info foldr
:doc foldr
:t foldl
:info foldl
:doc foldl
:t map
:info map
:doc map
Or better, open hoogle.haskell.org and search each of the above mentioned functions and click on the first link.
But I agree that Haskell documentation are difficult to read, especially for beginners. I'm a beginner and I have a lot of difficulty reading and understanding them.
Here's a function that uses map and foldr to show how foldr works:
printFoldr xs = foldr (\x acc -> "(" ++ x ++ " + " ++ acc ++ " )") "0" $ map show xs
Now running watch this:
printFoldr [1..5]
-- outputs the following:
"(1 + (2 + (3 + (4 + (5 + 0 ) ) ) ) )"
This shows us how foldr is evaluated. Before going into how foldr is evaluated, let's look briefly at map.
map show [1..5]
-- outputs the following:
["1","2","3","4","5"]
This means that map takes 2 arguments. A list and a function that is applied to each element of the list. The result is a new list with the function applied to each element. Thus, applying show to each number outputs their string representation.
Back to foldr. foldr takes 3 arguments:
a function of type a -> b -> b
an initial value of type b
a list of type [a]
foldr takes each and every value of the provided list and applies this function to it. What is special is that map retains the output of the function over each iteration and passes it to the function as its second argument on the next run. Therefore it is convenient to write the function that is passed foldr as follows: (\el acc -> do something). Now on the next iteration of foldr, acc will hold the value of the previous run and el will be the current element from the list. BTW, acc stands for accumulator and el for element. This enables us to reduce elements of the provided list to something completely new.
As you can see in printFoldr, the initial value is just an empty string but it gradually adds the lists elements to it showing how it would have reduced the elements of the list to their sum.
Here's an idea:
a1-a2+a3-a4+...
=
a1-(a2-(a3-(a4-(...(an-0)...))))
This fits pretty well to the foldr pattern of recursion,
foldr f z [a1,a2,a3,a4,...,an]
=
a1`f`(a2`f`(a3`f`(a4`f`(...(an`f`z)...))))
So it can be coded by setting f = ... and z = ... and calling
asum :: (Num a) => [a] -> a
asum xs = foldr f z xs
where
f = (...)
z = (...)
You will need to complete this definition.
For the XOR of a list of Booleans, assuming it is to be True if one and only one of them is True, and False otherwise, we can imagine this sequence of transformations:
[ True, False, False, True, True, False, ...]
==>
[ t, f, f, t, t, f, ...]
where t and f are some specially chosen numbers. And then we can find the sum of this second list (not alternating sum, just a sum of a list of numbers) and check whether it is equal to ... some (other?) special number, let's call it n1:
xor :: [Bool] -> Bool
xor bools = (aNumber ... n1)
where
list1 = bools
list2 = fun1 transform list1
transform False = f
transform True = t
f = ...
t = ...
aNumber = sum list2
n1 = ...
fun1 = ...
sum listOfNums = ...
fun1 is the function which transforms each element of its argument list according to the given function, called transform above. It is one of the two functions left from the three you were given, considering we've already been using foldr.
sum is to be implemented by using the last function that's left.
FYI,
map foo [a1,a2,a3,...,an]
=
[foo a1, foo a2, foo a3, ..., foo an]
and
foldl f z [a1,a2,a3,...,an]
=
((((z`f`a1)`f`a2)`f`a3)...)`f`an

Why do I get this error when trying to map on a list of lists?

I'm trying to use map to write a function that takes the last elements of a list of lists. For example:
[ [0,0,4],[2,4,2],[1,3,5],[3,1,1] ] => [4,2,5,1]
I've written this:
func l = map (last l)
and got this error:
> ERROR - Type error in application
Expression : func [[0,0,4],[2,4,2],[1,3,5],[3,1,1]]
Term : [[0,0,4],[2,4,2],[1,3,5],[3,1,1]]
Type : [[c]]
Does not match : [a -> b]
What's the right way to do this?
You're doing the wrong thing with last. What you are trying to do is apply it to each inner list inside the outer list l. What you're actually doing is applying it to the outer list l itself, and then map makes no sense.
You need to write map last l instead.
You can see the right form of the arguments to map from its type:
map :: (a -> b) -> [a] -> [b]
This means that map takes two arguments, one of type a -> b and another of type [a].
Note that in your code you're only giving it the first argument (last l). This is a valid thing to do in Haskell in general (look up "partial application" or "currying"), but here the first argument is supposed to be a function and last l certainly isn't.
In this case your list l is the thing of type [a], so a = [Integer] (ignoring numeric overloading). The first argument should be a function of type [Integer] -> b, and you want to use last which means that b = Integer. So the end result will be of type [Integer] as wanted.
Try
func l = map last l
no parenthesis.
If you take a look at the types in func [[0,0,4],[2,4,2],[1,3,5],[3,1,1] call you'll notice that since l = [[0,0,4],[2,4,2],[1,3,5],[3,1,1]], the type of l is [[c]] but then type of last l is [c] while map expects [a -> b] as it's first argument.
Or even by using point free notation:
f = map last
Which, in ghci, yields the type:
GHCI> let f = map last
GHCI> :t f
f :: [[b]] -> [b]
GHCI> f [ [0,0,4],[2,4,2],[1,3,5],[3,1,1] ]
[4,2,5,1]

using reverse on a self-defined list in Haskell

I did a self-defined data type called Queue and trying to enqueue Integers at the end of the "list".
data Queue = Ele Int Queue | Nil
-- [..] some other Functions
enqueue :: Int -> Queue -> Queue
enqueue x Nil = (Ele x Nil)
enqueue x (Ele _ restEles) = reverse (Ele x reverse restEles)
I get the error:
"Couldn't match expected type Queue' with actual type[a0]'".
I think that is, because the function doesn't know how to handle my datatype. Am I right here? How can I fix this? Do I have to write my own reverse function? And if could you help me with that, because I am still learning Haskell and don't understand this:
reverse = foldl (flip (:)) []
Yes, you have defined a new datatype. Even though it's structurally similar to lists, Haskell will treat it as completely different. So you have to define a new reverse function indeed, or alternatively, define a function converting your type into a standard list and back.
But for enqueue you do not necessarily need reverse. You can just recursively invoke enqueue on restEles in the case for Ele and put the first element back in front of the result.
Here's a pattern for the directly recursive definition for you to complete:
enqueue :: Int -> Queue -> Queue
enqueue x Nil = Ele x Nil
enqueue x (Ele firstEle restEles) = ...
For ..., you have to do what I said above: call enqueue recursively on the rest of the
elements and put the first elements back on top.
The type of reverse is:
reverse :: [a] -> [a]
Queue is not a [a]. You need to implement your own reverseQueue function that understands your data type.
As for the second part of your question:
reverse :: [a] -> [a]
reverse = foldl (flip (:)) []
First, make sure you understand foldl. It's a powerful high-order function, which means it can be used to implement a lot of other functions (sum,map,filter and of course reverse). You can read about it here.
Now, let's take a look at a simpler version:
reverse :: [a] -> [a]
reverse xs = foldl (\ys y -> y:ys) [] xs
\ys y -> y:ys is a very simple function: it takes a list (ys) and a value (y) and insert the value before the list (y:ys). So our course of plan is: start with the empty list ([]), insert the first item in xs to its left, take the result and insert the second item to its left and so on.
Let's simulate it with a simple list - [1,2,3]:
We start with the empty list - []
Add the first item (1) to it's left: [1]
Add the second item (2) to the left of [1]: [2,1]
Add the third item (3) to the left of [2,1]: [3,2,1]
And we've successfully reversed [1,2,3].
Now, flip is a function that takes a function and "flips" it's arguments. so if subtract a b is a-b, then (flip subtract) a b is equal to subtract b a - b-a. So if (:) is a function that takes an item y and a list ys and adds the item to the beginning of the list, then flip (:) is the same function with flipped arguments - it takes a list and an item, much like our function - \ys y -> y:ys. So we can replace the two of them:
reverse :: [a] -> [a]
reverse xs = foldl (flip (:)) [] xs
And now we write in pointfree style and eliminate xs from both sides of the equation and get the final version:
reverse :: [a] -> [a]
reverse = foldl (flip (:)) []

Haskell mapping function to list

I am new to Haskell and I have the following problem. I have to create a list of numbers [f1, f2, f3...] where fi x = x ^ i. Then I have to create a function that applies the fi to a list of numbers. For example if I have a list lis = [4,5,6,7..] the output would be [4^1, 5^2,6^3, 7^4...]. This is what I have written so far :
powers x= [x^y |y<-[1,2,3,4]]
list = [1,2,3,4]
match :: (x -> xs) -> [x] -> [xs]
match f [] = []
match f (x:xs) = (f x) : ( match f xs )
So if I put the list = [1,2,3] the output is [1,1,1,1][2,4,8,16],[3,9,27,81] instead of [1,4,27]
Can you please tell me what is wrong and point me to the right direction?
The first issue is that powers is of type Int -> [Int]. What you really want, I think, is something of type [Int -> Int] -- a list of Int -> Int functions instead of a function that takes an Int and returns a list of Int. If you define powers like so:
powers = [(^y) | y <- [1..4]]
you can use zipWith to apply each power to its corresponding element in the list, like so:
zipWith ($) powers [1,2,3] -- returns [1,4,27]
The ($) applies its left (first) argument to its right (second) argument.
Note that using powers as defined here will limit the length of the returned list to 4. If you want to be able to use arbitrary length lists, you want to make powers an infinite list, like so:
powers = [(^y) | y <- [1..]]
Of course, as dave4420 points out, a simpler technique is to simply use
zipWith (^) [1,2,3] [1..] -- returns [1,4,27]
Your match is the standard function map by another name. You need to use zipWith instead (which you can think of as mapping over two lists side-by-side).
Is this homework?
You are currently creating a list for every input value.
What you need to do is recursively compute the appropriate
power for each input value, like this:
match f [] = []
match f (x:xs) y = (f x y) : (match f xs y+1)
Then, you can call this as match pow [1, 2, 3] 1.
This is equivalent to using zipWith and providing the desired function (pow), your input list ([1, 2, 3]) and the exponent list (a lazy one to infinity list) as arguments.

The composition of functions in a list of functions!

I need to define a function 'Compose' which takes a list 'L' which is a list of functions. When I specify a parameter that will suit all the functions in the list, the last function evaluates itself using this param. The result is then passed to the second last function and so on until we get to the first item (function) in the list and we get the final result.
E.g.
Compose ( ( fn N -> N + 1 ) ^ ( fn N -> 2 * N ) ^ # ) 3 .
give the answer 7.
I have to write this in a functional programming language called SAL (simple applicative language) devised by a lecturer in my college (hence funny syntax above ( ^ seperates list items and # marks end of list)).
If any solutions could be written in pseudo-code bearing in mind I can't use loops, variables etc. that would be much appreciated. Apparently the solution is a one-line answer. I imagine it involves recursion (99% of our task functions do!).
Also I don't understand Haskell (guess I'll have to learn!) so psuedo code or even plain English would be great. –
Thanks a bunch.
If the solution is a one-line answer, it could be something involving a fold:
compose :: [a -> a] -> a -> a
compose fs v = foldl (flip (.)) id fs $ v
http://haskell.org/haskellwiki/Compose
You can also implement it as a right fold, which works the way you want:
compose = foldr (.) id
*Main> let compose = foldr (.) id
*Main> compose [\x -> x+1, \x -> 2 * x, id] 3
7
in haskell:
compose :: a -> [a -> a] -> a
compose a (x:xs) = x (compose a xs)
compose a [] = a
Dan kind of gives it away, but here's a hint on how to do it yourself. You can recurse over numbers:
0! = 1
n! = (n-1)! * n
You can also recurse over structure. A list, for example, has a recursive structure, broken down into two cases: an empty list, and an item followed by the rest of the list. In no particular language:
List := Item x List
| Nil
Item marks the head of the list, x is the value stored in the head, and List is the tail. In this grammar, your list would be written:
Item ( fn N -> N + 1 ) Item ( fn N -> 2 * N ) Nil
The rule for a list in the syntax your professor invented could be written recursively as:
List := x ^ List
| #
A function on a list must recurse over this structure, which means it handles each of the two cases:
sum l:List = Nil -> 0
| Item x xs:List = x + sum xs
The recursion, specifically, is the term sum l:List = x + sum xs. Writing this function using the professor's syntax left as an exercise.
In your problem, your metafunction takes a list of functions and must return a function. Consider each case, the empty list and an item (the head) followed by a list (the tail). In the latter case, you can recursively use your function to get a function from the tail, then combine that somehow with the head to return a function. That's the gist, at any rate.
The same using monoids, point-free
import Data.Monoid
compose :: [a -> a] -> a -> a
compose = appEndo . mconcat . map Endo
Or somewhat more generally:
import Data.Monoid
compose :: (Functor t, Foldable t) => t (a -> a) -> a -> a
compose = appEndo . foldl1 (<>) . fmap Endo
Here's what I used:
compose :: [a -> a] -> a -> a
compose list startingvalue = foldl (\x f -> f x) startingvalue list

Resources