what does this function do in Haskell? - haskell

what does this function in Haskel do ?
I don't understand the way the recursion works here
f[]=[]
f(x:xs)=x: [y|y <- f xs, x/=y]

f[]=[]
f(x:xs) = x : [y|y <- f xs, x/=y]
This function removes duplicates from a list. Here's how it works:
Base case, the list is empty, so it returns the empty list.
Otherwise you take the first element x, and assume (inductive hypothesis) that f xs gives you the list without duplicates. Now, the only thing you have to do is make sure that you don't insert x again. So, the list comprension means: take all the rest of the elements (which by inductive hypothesis are unique), but remove the x.
Does it feel right now?
ps. you can write the second clause also as:
f(x:xs) = x : filter (/= x) (f xs)

Seems to me that it eliminates any duplicate entries in the list.
Here's how it works:
f[] = [] means that, when the input is an empty list, the output will be an empty list.
Then, f(x:xs) = x: [y|y <- f xs, x/=y] uses what's called a list comprehension. It takes the head of the input list, and then appends the list comprehension.
The list comprehension reads like this: "y such that y is in f(xs), and y doesn't equal x"
So it's the list of elements in f(xs) that don't equal the head element.

Related

I don't see what does "even" in the piece of code do?

ghci> let xxs=[[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]
ghci> [[x|x<- xs,even x]|xs<- xxs]
[[2,2,4],[2,4,6,8],[2,4,2,6,2,6]]
This piece of code relates to list comprehension. But i don't see how the program goes with "even"
A Haskell list comprehension expression has three types of elements at the right side of the list comprehension:
generators, of the form var <- list-expr;
filters of the form bool-expr; and
local definitions of the form let var = expr.
The even x part is thus a filter. It means that only if the filter is satisfied, so even x results in True, that element is a candidate for the rest of the list comprehension and thus eventually result in a branch of elements added to the list.
So here the expression thus has two components:
[x | x <- xs, even x ]
-- \__ __/ \__ _/
-- v v
-- generator filter
we thus iterate over the elements in xs and then for each element check if that element is even, if it is, we add x to the result.
The above can however be written as just:
filter even xs
which basically describe what we do here: we filter a list xs such that the result is a list that only contains the elements of xs that are even.

Using List Comprehension in place of Recursion

I am curious whether or not using list comprehension in place of recursion is possible for the following example.
The function replaceFirst that takes in an an element and a list and replaces the first occurrence of the element from the list.
This can be done using recursion as follows:
replaceFirst _ [] = []
replaceFirst elem y (x:xs) | x==y = (elem:xs)
| otherwise = x:replaceFirst elem y xs
My question is, can this recursive function, or a similar recursive function that operates on the first occurrence of an element in a list, be replaced with a list comprehension function? Why or why not? (I am more concerned with the reasoning than the actual code).
List comprehensions are syntactic sugar for various forms of map, filter, and concatMap. If your recursive function can be described in terms of these, then you can rewrite it to a list comprehension. They can't short circuit, as you do above, nor can they pass accumulating state.
Your replaceFirst would seem to require an accumulator to "tell" later elements in the list about the appearance of earlier elements. I think this makes it difficult or impossible to write using only list comprehension syntax.
List comprehension, inspired by leftaroundabout:
replaceFirst elem y xs = [a | let b = break (==y) xs
c = if not (null $ snd b)
then fst b ++ [elem] ++ tail (snd b)
else fst b
, a <- c]

Haskell List Comprehension creating function

I am new to Haskell and am trying to learn the basics. I am having a hard time understanding how to manipulate the contents of a list.
Assume I have the following list and I would like to create a function to subtract 1 from every element in the list, where I can simply pass x to the function, how would this be done?
Prelude>let x = 1:2:3:4:5:[]
Something like:
Prelude>subtractOne(x)
(You can write 1:2:3:4:5:[] more simply as [1,2,3,4,5] or even [1..5].)
Comprehensions
You'd like to use list comprehensions, so here it is:
subtractOne xs = [ x-1 | x <- xs ]
Here I'm using xs to stand for the list I'm subtracting one from.
The first thing to notice is x <- xs which you can read as "x is taken from xs". This means we're going to take each of the numbers in xs in turn, and each time we'll call the number x.
x-1 is the value we're calculating and returning for each x.
For more examples, here's one that adds one to each element [x+1|x<-xs] or squares each element [x*x|x<-xs].
More than one list
Let's take list comprehension a little further, to write a function that finds the squares then the cubes of the numbers we give it, so
> squaresAndCubes [1..5]
[1,4,9,16,25,1,8,27,64,125]
We need
squaresAndCubes xs = [x^p | p <- [2,3], x <- xs]
This means we take the powers p to be 2 then 3, and for each power we take all the xs from xs, and calculate x to the power p (x^p).
What happens if we do that the other way around?
squaresAndCubesTogether xs = = [x^p | x <- xs, p <- [2,3]]
We get
> squaresAndCubesTogether [1..5]
[1,1,4,8,9,27,16,64,25,125]
Which takes each x and then gives you the two powers of it straight after each other.
Conclusion - the order of the <- bits tells you the order of the output.
Filtering
What if we wanted to only allow some answers?
Which numbers between 2 and 100 can be written as x^y?
> [x^y|x<-[2..100],y<-[2..100],x^y<100]
[4,8,16,32,64,9,27,81,16,64,25,36,49,64,81]
Here we allowed all x and all y as long as x^y<100.
Since we're doing exactly the same to each element, I'd write this in practice using map:
takeOne xs = map (subtract 1) xs
or shorter as
takeOne = map (subtract 1)
(I have to call it subtract 1 because - 1 would be parsed as negative 1.)
You can do this with the map function:
subtractOne = map (subtract 1)
The alternative solution with List Comprehensions is a little more verbose:
subtractOne xs = [ x - 1 | x <- xs ]
You may also want to add type annotations for clarity.
You can do this quite easily with the map function, but I suspect you want to roll something yourself as a learning exercise. One way to do this in Haskell is to use recursion. This means you need to break the function into two cases. The first case is usually the base case for the simplest kind of input. For a list, this is an empty list []. The result of subtracting one from all the elements of the empty list is clearly an empty list. In Haskell:
subtractOne [] = []
Now we need to consider the slightly more complex recursive case. For any list other than an empty list, we can look at the head and tail of the input list. We will subtract one from the head and then apply subtractOne to the rest of the list. Then we need to concatenate the results together to form a new list. In code, this looks like this:
subtractOne (x:xs) = (x - 1) : subtractOne xs
As I mentioned earlier, you can also do this with map. In fact, it is only one line and the preferred Haskellism. On the other hand, I think it is a very good idea to write your own functions which use explicit recursion in order to understand how it works. Eventually, you may even want to write your own map function for further practice.
map (subtract 1) x will work.
subtractOne = map (subtract 1)
The map function allows you to apply a function to each element of a list.

Haskell: Minimum sum of list

So, I'm new here, and I would like to ask 2 questions about some code:
Duplicate each element in list by n times. For example, duplicate [1,2,3] should give [1,2,2,3,3,3]
duplicate1 xs = x*x ++ duplicate1 xs
What is wrong in here?
Take positive numbers from list and find the minimum positive subtraction. For example, [-2,-1,0,1,3] should give 1 because (1-0) is the lowest difference above 0.
For your first part, there are a few issues: you forgot the pattern in the first argument, you are trying to square the first element rather than replicate it, and there is no second case to end your recursion (it will crash). To help, here is a type signature:
replicate :: Int -> a -> [a]
For your second part, if it has been covered in your course, you could try a list comprehension to get all differences of the numbers, and then you can apply the minimum function. If you don't know list comprehensions, you can do something similar with concatMap.
Don't forget that you can check functions on http://www.haskell.org/hoogle/ (Hoogle) or similar search engines.
Tell me if you need a more thorough answer.
To your first question:
Use pattern matching. You can write something like duplicate (x:xs). This will deconstruct the first cell of the parameter list. If the list is empty, the next pattern is tried:
duplicate (x:xs) = ... -- list is not empty
duplicate [] = ... -- list is empty
the function replicate n x creates a list, that contains n items x. For instance replicate 3 'a' yields `['a','a','a'].
Use recursion. To understand, how recursion works, it is important to understand the concept of recursion first ;)
1)
dupe :: [Int] -> [Int]
dupe l = concat [replicate i i | i<-l]
Theres a few problems with yours, one being that you are squaring each term, not creating a new list. In addition, your pattern matching is off and you would create am infinite recursion. Note how you recurse on the exact same list as was input. I think you mean something along the lines of duplicate1 (x:xs) = (replicate x x) ++ duplicate1 xs and that would be fine, so long as you write a proper base case as well.
2)
This is pretty straight forward from your problem description, but probably not too efficient. First filters out negatives, thewn checks out all subtractions with non-negative results. Answer is the minumum of these
p2 l = let l2 = filter (\x -> x >= 0) l
in minimum [i-j | i<-l2, j<-l2, i >= j]
Problem here is that it will allow a number to be checkeed against itself, whichwiull lend to answers of always zero. Any ideas? I'd like to leave it to you, commenter has a point abou t spoon-feeding.
1) You can use the fact that list is a monad:
dup = (=<<) (\x -> replicate x x)
Or in do-notation:
dup xs = do x <- xs; replicate x x; return x
2) For getting only the positive numbers from a list, you can use filter:
filter (>= 0) [1,-1,0,-5,3]
-- [1,0,3]
To get all possible "pairings" you can use either monads or applicative functors:
import Control.Applicative
(,) <$> [1,2,3] <*> [1,2,3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
Of course instead of creating pairs you can generate directly differences when replacing (,) by (-). Now you need to filter again, discarding all zero or negative differences. Then you only need to find the minimum of the list, but I think you can guess the name of that function.
Here, this should do the trick:
dup [] = []
dup (x:xs) = (replicate x x) ++ (dup xs)
We define dup recursively: for empty list it is just an empty list, for a non empty list, it is a list in which the first x elements are equal to x (the head of the initial list), and the rest is the list generated by recursively applying the dup function. It is easy to prove the correctness of this solution by induction (do it as an exercise).
Now, lets analyze your initial solution:
duplicate1 xs = x*x ++ duplicate1 xs
The first mistake: you did not define the list pattern properly. According to your definition, the function has just one argument - xs. To achieve the desired effect, you should use the correct pattern for matching the list's head and tail (x:xs, see my previous example). Read up on pattern matching.
But that's not all. Second mistake: x*x is actually x squared, not a list of two values. Which brings us to the third mistake: ++ expects both of its operands to be lists of values of the same type. While in your code, you're trying to apply ++ to two values of types Int and [Int].
As for the second task, the solution has already been given.
HTH

remove first occurence of element in the list using list comprehension

I can remove all occurences of element in the list:
*Main> let d = [1, 2, 3, 4, 5, 6]
*Main> d
[1,2,3,4,5,6]
*Main> [x | x <- d, not(x == 2)]
[1,3,4,5,6]
I just wondering if there is any possibility to remove only FIRST occurence of element in the list, but using list comprehension?
No, there isn't. The list comprehension
[ x | x <- d, GUARD ]
is equivalent by definition to the following:
let ok x = if GUARD then [x] else []
ok _ = []
in concatMap ok d
By the definition of 'if', GUARD must be a pure boolean expression (i.e. evaluate to True of False alone), so it cannot keep track of state as you map over the list (assuming you're going to play by the rules).
Having said that, there is one way around this that uses comprehensions: zip state into your input list and run a list comprehension on that composite list. This composite list might have a type of something like [(Int, Bool)] where the Bool indicates whether this is the first item in the list. You then do something like:
[ x | (x, isFirst) <- zip d (findFirsts d), not (x == 2 && isFirst)]
where the implementation of findFirsts d is left as an exercise to the reader.
But you wouldn't want to do this in this particular case. It's a bad solution here because it basically means you're going to go through the list at least twice, once to figure out which items are the Firsts, and once to actually filter out the item(s) you don't want. If you implemented findFirsts naively, you might be looking at a bunch more work than even that. Not the right tool for the job!
For certain problems, though, like checking for the head or incorporating the specific position of an item into your results (as hvr has demonstrated), this can be a very effective technique.
Two other ways:
Use monadic computations to carry state as you sequentially iterate through the list. Might be OK for cases where you want to traverse arbitrary or complicated structures, or where your computation is going to be complicated, but in this case, you're better off if you:
Just use a simple recursive function solution, which is what Data.List.delete and deleteBy do.
For the record I wanted to point out that the delete function in the Data.List module provides exactly the behaviour you describe.
So you could cheat a bit and just use delete in your list comprehension:
> let l = [1,2,3,2,1]
> [x | x <- delete 2 l]
[1,3,2,1]
I guess this doesn't count.
...so, I was curious how to do this and here's a solution which doesn't use delete:
-- Removes the first occurrence of '2' in 'l', if any.
[x | (x,y) <- zip l [0..], let idx = elemIndex 2 l, idx == Nothing || y /= fromJust idx]
The idea is to first turn the list into a list of tuples where the second element of each tuple is the index of the element, e.g. "abcba" becomes [('a',0),('b',1),('c',2),('b',3),('a',4)]. Then we take each first element of all tuples for which the second tuple element does not equal the value returned by 'elemIndex' (which returns the position of the first occurance of the given element). For instance, elemIndex 'b' "abca" yields 2, so we take the first elements of all tuples where the second element is not 2. And that yields "acba".
The following removes the element only if occuring in head position:
[ x | (i, x) <- zip [0..] d, if i == 0 then x /= 2 else True ]
(which wasn't the question)
Not directly. List comprehensions are equivalent to using concat and map only. They map elements uniformly - if a is changed to b (or removed, or changed into several elements) then all occurences of a will do the same.
An ugly way would be to tag elements with numbers and search for the first one:
f r x = let x' = zip x [0..]
(_,n) = head [v | v <- x', fst v == r]
in [y | (y,m) <- x', y /= r || m /= n]
First zip can be expressed with LC if you use extension "parallel list comprehensions". This is extremely nonidiomatic, better use explicit recursion or Data.List.delete.

Resources