Let's say I have a list of values to which I want to apply a sequence of operations until I get a final result:
[0, 1, 2]
firstOperation xs = map (+1) xs
secondOperation xs = filter even xs
thirdOperation xs = sum xs
Although I am sure there are other better ways to handle this, the only one I currently know is to define a function that calls all these functions nested one inside another:
runAllOperations xs = thirdOperation (secondOperation (firstOperation xs))
but this is both ugly and raises the problem that if I have 10 operations, turns this bit of code into a maintanance nightmare.
What is the correct way of implementing something of the kind here? Keep in mind the example I gave above is just a oversimplification of what I am facing on my current project.
. or $ are way more readable than ( and )
runAllOperations xs = thirdOperation $ secondOperation $ firstOperation xs
or
runAllOperations = thirdOperation . secondOperation . firstOperation
If you can make a list of all the operations, you can then fold the composition operator over that list:
foldr (.) id fns
Then you can apply the result of that to the initial values.
Though you might need to apply a final reduction step separately.
Related
I have many lists. Say for short [[1,2],[3,4]].
I need to generate all changes of signs of each element. Thus, for the short example, the result would be
[[1,2],[3,4],[-1,2],[1,-2],[-1,-2],[-3,4],[3,-4],[-3,-4]]
Is there a package to perform such an operation ? Otherwise what algorithm could I use ? (I confess I have not thought a lot about it ...).
It this can help, all my lists have the same length.
Edit
Hmm.. maybe an idea like that:
x = [[2*i,2*j] | i <- [1, -1], j <- [-1,1]]
x
[[2,-2],[2,2],[-2,-2],[-2,2]]
The problem can be broken down to 2 steps:
For a given list of numbers, generate all the possible signs
For the list of lists, apply the function from (1) to each list, then concat the results.
For 1. you can write a simple recursive function that first processes the tail of the list, then for each resulting combination, it generates two versions for the two signs.
signs :: [Int] -> [[Int]]
signs [] = [[]]
signs (x : xs)
= let ps = signs xs
in map (x :) ps ++ map ((-x) :) ps
For 2. simply map the signs function over the input, and concat them. This is what the concatMap function does:
signsAll :: [[Int]] -> [[Int]]
signsAll = concatMap signs
I tried to use an applicative here, because it looks like you are almost there
[id,negate] <*> [3,4]
but it turned out that I need sequence and map, which, in this case, can be combined into a traverse:
traverse (\x->[x,-x]) [3,4]
[[3,4],[3,-4],[-3,4],[-3,-4]]
As others mentioned, now you need concatMap for your function:
concatMap (traverse (\x->[x,-x])) [[3,4],[1,2]]
[[3,4],[3,-4],[-3,4],[-3,-4],[1,2],[1,-2],[-1,2],[-1,-2]]
I want to create a function that returns every third int from a list of ints without using any predefined functions. For example, everyThird [1,2,3,4,5] --> [1,4]
everyThird:: [a] -> [a]
Could I just continue to iterate over the list using tail and appending to a new list every third call? I am new to Haskell and very confused with all of this
One other way of doing this is to handle three different base cases, in all of which we're at the end of the list and the list is less than three elements long, and one recursive case, where the list is at least three elements long:
everyThird :: [a] -> [a]
everyThird [] = []
everyThird [x] = [x]
everyThird [x, _] = [x]
everyThird (x:_:_:xs) = x:everyThird xs
You want to do exactly what you said: iterate over the list and include the element only on each third call. However, there's a problem. Haskell is a funny language where the idea of "changing" a variable doesn't make sense, so the usual approach of "have a counter variable i which tells us whether we're on the third element or not" won't work in the usual way. Instead, we'll create a recursive helper function to maintain the count for us.
everyThird :: [Int] -> [Int]
everyThird xs = helper 0 xs
where helper _ [] = []
helper 0 (x : xs) = x : helper 2 xs
helper n (_ : xs) = helper (n - 1) xs
We have three cases in the helper.
If the list is empty, stop and return the empty list.
If the counter is at 0 (that is, if we're on the third element), make a list starting with the current element and ending with the rest of the computation.
If the counter is not at zero, count down and continue iteration.
Because of the way pattern matching works, it will try these three statements in order.
Notice how we use an additional argument to be the counter variable since we can't mutate the variable like we would in an imperative language. Also, notice how we construct the list recursively; we never "append" to an existing list because that would imply that we're mutating the list. We simply build the list up from scratch and end up with the correct result on the first go round.
Haskell doesn't have classical iteration (i.e. no loops), at least not without monads, but you can use similar logic as you would in a for loop by zipping your list with indexes [0..] and applying appropriate functions from Data.List.
E.g. What you need to do is filter every third element:
everyThirdWithIndexes list = filter (\x -> snd x `mod` 3 == 0) $ zip list [0..]
Of course you have to get rid of the indexes, there are two elegant ways you can do this:
everyThird list = map (fst) . everyThirdWithIndexes list
-- or:
everyThird list = fst . unzip . everyThirdWithIndexes list
If you're not familiar with filter and map, you can define a simple recursion that builds a list from every first element of a list, drops the next two and then adds another from a new function call:
everyThird [] = [] -- both in case if the list is empty and the end case
everyThird (x:xs) = x : everyThird (drop 2 xs)
EDIT: If you have any questions about these solutions (e.g. some syntax that you are not familiar with), feel free to ask in the comments. :)
One classic approach:
everyThird xs = [x | (1,x) <- zip (cycle [1..3]) xs]
You can also use chunksOf from Data.List.Split to seperate the lists into chunks of 3, then just map the first element of each:
import Data.List.Split
everyThird :: [a] -> [a]
everyThird xs = map head $ chunksOf 3 xs
Which works as follows:
*Main> everyThird [1,2,3,4,5]
[1,4]
Note: You may need to run cabal install split to use chunksOf.
I have two arrays of equal size and I want to combine them element-wise. What is the best way to do this? The array package doesn't seem to provide a zipWith equivalent function.
I'm reluctant to make my own function because the main way I can think of doing this is to convert back and forth with lists. I care about speed and I assume this way is not the most efficient way.
Option 1: use repa. Might get some performance benefit from the parallelism as well, should you care about it.
Option 2: just get indices using bounds. I would suggest avoiding list comprehensions in general; though the other answer uses them correctly in this case, it may be worthwhile to get in the habit of doing the right thing.
zipWithArr f xs ys = listArray (bounds xs) $ fmap (liftA2 f (xs !) (ys !)) (range (bounds xs))
The reason that this works is that Haskell's lists are lazy, and we can generally treat them as control structures (due to various optimizations), though we can not treat them as containers. Moreover, GHC evaluates an expression at most once per lambda, so in general you do not need to worry that this will be done inefficiently.
It's pretty easy to cook one up yourself:
zipWithA f xs ys = listArray (bounds xs) [f (xs ! i) (ys ! i) | i <- range (bounds xs)]
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.
Many times I see functions which operate on the head of a list, e.g:
trimHead ('\n':xs) = xs
trimHead xs = xs
then I see the the definition:
trimTail = reverse . trimHead . reverse
then I see:
trimBoth = trimHead . trimTail
They are clean, but are trimTail and trimBoth efficient? Is there a better way?
Consider this alternative implementation
trimTail2 [] = []
trimTail2 ['\n'] = []
trimTail2 (x:xs) = x : trimTail2 xs
trimBoth2 = trimHead . trimTail2
It's easy to confirm that trimTail and trimBoth require that the entire list be evaluated, while trimTail2 and trimBoth2 only evaluate as much of the list as is necessary.
*Main> head $ trimTail ('h':undefined)
*** Exception: Prelude.undefined
*Main> head $ trimBoth ('h':undefined)
*** Exception: Prelude.undefined
*Main> head $ trimTail2 ('h':undefined)
'h'
*Main> head $ trimBoth2 ('h':undefined)
'h'
This implies that your version is going to be less efficient if the whole result is not needed.
Assuming the whole list is to be evaluated (if you don't need the whole list, why are you trimming the end?), it's about half as efficient as you can get out of immutable lists, but it has the same asymptotic complexity O(n).
The new list requires at least:
You have to find the end: n pointer traversals.
You have to modify the end, and thus what points to the end, etc.: n cons of existing data with new pointers.
reverse . trimHead . reverse performs roughly twice this:
The first reverse performs n pointer traversals and n cons.
trimHead possibly performs 1 pointer traversal.
The second reverse performs n pointer traversals and n cons.
Is this worth worrying about? In some circumstances, maybe. Is the code too slow, and is this called a lot? In others, maybe not. Benchmark! The implementation with reverse is nice and easy to understand, and that's important.
There is a fairly natural recursive step-through-the-list solution, which will only evaluate as much of the output as is consumed, so in the case that you don't know whether you need the whole string, you can possibly save some evaluation.
It isn't efficient in the sense, that streaming is impossible, because the whole list needs to be evaluated to get even a single element. But a better solution is difficult, as you need to evaluate the rest of the list to know, whether a line-break is to be trimmed or not. A slightly more efficient way would be to look ahead whether the linebreak is to be trimmed and react appropriately:
trimTail, trimHead, trimBoth :: String -> String
trimTail ('\n':xs) | all (=='\n') xs = ""
trimTail (x:xs) = x : trimTail xs
trimHead = dropWhile (=='\n')
trimBoth = trimTail . trimHead
The solution above evaluates only as much as needed from the string to know, if the linebreak is to be trimmed. An even better method would be to incorporate the knowledge, that the next n chars are not to be trimmed. Implementing this is left as an exercise to the reader.
An even better (and shorter) way to write trimTail is this way (by rotsor):
trimTail = foldr step [] where
step '\n' [] = []
step x xs = x:xs
Generally, try to avoid reverse. Usually there is a better way to solve the problem.
Are trimHead and trimTail efficient?
They both take O(n) time (time directly proportional to the size of the list) since the entire list must be traversed twice in order to perform the two reverses.
Is there a better way?
Well, do you have to use lists? With Data.Sequence you can modify either end of the list in constant time. If you're stuck with lists, then check out the other solutions suggested here. If you can use Sequences instead, then just modify FUZxxl's answer to use dropWhileR.