Is (>>) supposed to discard all left-side output? - list

I think I do understand the list monad but then I found I am not. Here is the story.
Given list m and function k
> let m = [1..10]
> :t m
m :: [Integer]
> let k = replicate 2
> :t k
k :: a -> [a]
Playing with bind >>= give what I expect
> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
> :t m >>= k
m >>= k :: [Integer]
> m >>= k
[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10]
but for >>
Expected (from experiencing with IO monad, everything on left side would be discarded)
m >> m
[1,2,3,4,5,6,7,8,9,10]
Got
> :t (>>)
(>>) :: Monad m => m a -> m b -> m b
:t m >> m
m >> m :: [Integer]
> m >> m
[1,2,3,4,5,6,7,8,9,10,1,2,3,4,5 ... 9,10] -- truncated, real output is 100 elements
Please explain why >> is not behave like I expected (of course I must have misunderstanding) and what is the correct way to interpret >> ?

(>>) discards values from its first argument, but not effects. In this case it might be easier to see if you use lists with different types:
λ> "ab" >> [1,2,3,4]
[1,2,3,4,1,2,3,4]
Note how the values of the first list aren't used at all.
Remember the definition of (>>): a >> b = a >>= (\_ -> b). So this turns into "ab" >>= (\_ -> [1,2,3,4]), i.e. concat (map (\_ -> [1,2,3,4]) ['a','b']), i.e. concat [[1,2,3,4],[1,2,3,4]] (also, [i | _ <- "ab", i <- [1,2,3,4]]).
With [], (>>=) means something like "for each". The function on the right gets as an argument each value on the left. So (>>), which discards values, still means "for each" -- but this time it can't use the value, so it just means "the elements of the second list, repeated as many times as there are elements in the first list".

foo >> bar is the same as foo >>= \_ -> bar. So in the case of IO it executes the left action, ignoring the return value of that action, and then executes the right action. In the case of lists it maps over each element in the left list, ignoring the value of each elements, and inserts the right list at each point.
Another way to look at it is that >>= for lists is the same as flip concatMap, >> is the same as flip (concatMap . const).

Related

Breaking a list into sublists of a specified size using foldr

I'm taking a functional programming class and I'm having a hard time leaving the OOP mindset behind and finding answers to a lot of my questions.
I have to create a function that takes an ordered list and converts it into specified size sublists using a variation of fold.
This isn't right, but it's what I have:
splitList :: (Ord a) => Int -> [a] -> [[a]]
splitList size xs
| [condition] = foldr (\item subList -> item:subList) [] xs
| otherwise =
I've been searching and I found out that foldr is the variation that works better for what I want, and I think I've understood how fold works, I just don't know how I'll set up the guards so that when length sublist == size haskell resets the accumulator and goes on to the next list.
If I didn't explain myself correctly, here's the result I want:
> splitList 3 [1..10]
> [[1,2,3],[4,5,6],[7,8,9],[10]]
Thanks!
While Fabián's and chi's answers are entirely correct, there is actually an option to solve this puzzle using foldr. Consider the following code:
splitList :: Int -> [a] -> [[a]]
splitList n =
foldr (\el acc -> case acc of
[] -> [[el]]
(h : t) | length h < n -> (el : h) : t
_ -> [el] : acc
) []
The strategy here is to build up a list by extending its head as long as its length is lesser than desired. This solution has, however, two drawbacks:
It does something slightly different than in your example;
splitList 3 [1..10] produces [[1],[2,3,4],[5,6,7],[8,9,10]]
It's complexity is O(n * length l), as we measure length of up to n–sized list on each of the element which yields linear number of linear operations.
Let's first take care of first issue. In order to start counting at the beginning we need to traverse the list left–to–right, while foldr does it right–to–left. There is a common trick called "continuation passing" which will allow us to reverse the direction of the walk:
splitList :: Int -> [a] -> [[a]]
splitList n l = map reverse . reverse $
foldr (\el cont acc ->
case acc of
[] -> cont [[el]]
(h : t) | length h < n -> cont ((el : h) : t)
_ -> cont ([el] : acc)
) id l []
Here, instead of building the list in the accumulator we build up a function that will transform the list in the right direction. See this question for details. The side effect is reversing the list so we need to counter that by reverse application to the whole list and all of its elements. This goes linearly and tail-recursively tho.
Now let's work on the performance issue. The problem was that the length is linear on casual lists. There are two solutions for this:
Use another structure that caches length for a constant time access
Cache the value by ourselves
Because I guess it is a list exercise, let's go for the latter option:
splitList :: Int -> [a] -> [[a]]
splitList n l = map reverse . reverse . snd $
foldr (\el cont (countAcc, listAcc) ->
case listAcc of
[] -> cont (countAcc, [[el]])
(h : t) | countAcc < n -> cont (countAcc + 1, (el : h) : t)
(h : t) -> cont (1, [el] : (h : t))
) id l (1, [])
Here we extend our computational state with a counter that at each points stores the current length of the list. This gives us a constant check on each element and results in linear time complexity in the end.
A way to simplify this problem would be to split this into multiple functions. There are two things you need to do:
take n elements from the list, and
keep taking from the list as much as possible.
Lets try taking first:
taking :: Int -> [a] -> [a]
taking n [] = undefined
taking n (x:xs) = undefined
If there are no elemensts then we cannot take any more elements so we can only return an empty list, on the other hand if we do have an element then we can think of taking n (x:xs) as x : taking (n-1) xs, we would only need to check that n > 0.
taking n (x:xs)
| n > 0 = x :taking (n-1) xs
| otherwise = []
Now, we need to do that multiple times with the remainder so we should probably also return whatever remains from taking n elements from a list, in this case it would be whatever remains when n = 0 so we could try to adapt it to
| otherwise = ([], x:xs)
and then you would need to modify the type signature to return ([a], [a]) and the other 2 definitions to ensure you do return whatever remained after taking n.
With this approach your splitList would look like:
splitList n [] = []
splitList n l = chunk : splitList n remainder
where (chunk, remainder) = taking n l
Note however that folding would not be appropriate since it "flattens" whatever you are working on, for example given a [Int] you could fold to produce a sum which would be an Int. (foldr :: (a -> b -> b) -> b -> [a] -> b or "foldr function zero list produces an element of the function return type")
You want:
splitList 3 [1..10]
> [[1,2,3],[4,5,6],[7,8,9],[10]]
Since the "remainder" [10] in on the tail, I recommend you use foldl instead. E.g.
splitList :: (Ord a) => Int -> [a] -> [[a]]
splitList size xs
| size > 0 = foldl go [] xs
| otherwise = error "need a positive size"
where go acc x = ....
What should go do? Essentially, on your example, we must have:
splitList 3 [1..10]
= go (splitList 3 [1..9]) 10
= go [[1,2,3],[4,5,6],[7,8,9]] 10
= [[1,2,3],[4,5,6],[7,8,9],[10]]
splitList 3 [1..9]
= go (splitList 3 [1..8]) 9
= go [[1,2,3],[4,5,6],[7,8]] 9
= [[1,2,3],[4,5,6],[7,8,9]]
splitList 3 [1..8]
= go (splitList 3 [1..7]) 8
= go [[1,2,3],[4,5,6],[7]] 8
= [[1,2,3],[4,5,6],[7,8]]
and
splitList 3 [1]
= go [] 1
= [[1]]
Hence, go acc x should
check if acc is empty, if so, produce a singleton list [[x]].
otherwise, check the last list in acc:
if its length is less than size, append x
otherwise, append a new list [x] to acc
Try doing this by hand on your example to understand all the cases.
This will not be efficient, but it will work.
You don't really need the Ord a constraint.
Checking the accumulator's first sublist's length would lead to information flow from the right and the first chunk ending up the shorter one, potentially, instead of the last. Such function won't work on infinite lists either (not to mention the foldl-based variants).
A standard way to arrange for the information flow from the left with foldr is using an additional argument. The general scheme is
subLists n xs = foldr g z xs n
where
g x r i = cons x i (r (i-1))
....
The i argument to cons will guide its decision as to where to add the current element into. The i-1 decrements the counter on the way forward from the left, instead of on the way back from the right. z must have the same type as r and as the foldr itself as a whole, so,
z _ = [[]]
This means there must be a post-processing step, and some edge cases must be handled as well,
subLists n xs = post . foldr g z xs $ n
where
z _ = [[]]
g x r i | i == 1 = cons x i (r n)
g x r i = cons x i (r (i-1))
....
cons must be lazy enough not to force the results of the recursive call prematurely.
I leave it as an exercise finishing this up.
For a simpler version with a pre-processing step instead, see this recent answer of mine.
Just going to give another answer: this is quite similar to trying to write groupBy as a fold, and actually has a couple gotchas w.r.t. laziness that you have to bear in mind for an efficient and correct implementation. The following is the fastest version I found that maintains all the relevant laziness properties:
splitList :: Int -> [a] -> [[a]]
splitList m xs = snd (foldr f (const ([],[])) xs 1)
where
f x a i
| i <= 1 = let (ys,zs) = a m in ([], (x : ys) : zs)
| otherwise = let (ys,zs) = a (i-1) in (x : ys , zs)
The ys and the zs gotten from the recursive processing of the rest of list indicate the first and the rest of the groups into which the rest of the list will be broken up, by said recursive processing. So we either prepend the current element before that first subgroup if it is still shorter than needed, or we prepend before the first subgroup when it is just right and start a new, empty subgroup.

Implementing Haskell's `take` function using `foldl`

Implementing Haskell's take and drop functions using foldl.
Any suggestions on how to implement take and drop functions using foldl ??
take x ls = foldl ???
drop x ls = foldl ???
i've tried these but it's showing errors:
myFunc :: Int -> [a] -> [a]
myFunc n list = foldl func [] list
where
func x y | (length y) > n = x : y
| otherwise = y
ERROR PRODUCED :
*** Expression : foldl func [] list
*** Term : func
*** Type : a -> [a] -> [a]
*** Does not match : [a] -> [a] -> [a]
*** Because : unification would give infinite type
Can't be done.
Left fold necessarily diverges on infinite lists, but take n does not. This is so because left fold is tail recursive, so it must scan through the whole input list before it can start the processing.
With the right fold, it's
ntake :: Int -> [a] -> [a]
ntake 0 _ = []
ntake n xs = foldr g z xs 0
where
g x r i | i>=n = []
| otherwise = x : r (i+1)
z _ = []
ndrop :: Int -> [a] -> [a]
ndrop 0 xs = xs
ndrop n xs = foldr g z xs 0 xs
where
g x r i xs#(_:t) | i>=n = xs
| otherwise = r (i+1) t
z _ _ = []
ndrop implements a paramorphism nicely and faithfully, up to the order of arguments to the reducer function g, giving it access to both the current element x and the current list node xs (such that xs == (x:t)) as well as the recursive result r. A catamorphism's reducer has access only to x and r.
Folds usually encode catamorphisms, but this shows that right fold can be used to code up a paramorphism just as well. It's universal that way. I think it is beautiful.
As for the type error, to fix it just switch the arguments to your func:
func y x | ..... = .......
The accumulator in the left fold comes as the first argument to the reducer function.
If you really want it done with the left fold, and if you're really sure the lists are finite, two options:
ltake n xs = post $ foldl' g (0,id) xs
where
g (i,f) x | i < n = (i+1, f . (x:))
| otherwise = (i,f)
post (_,f) = f []
rltake n xs = foldl' g id xs r n
where
g acc x = acc . f x
f x r i | i > 0 = x : r (i-1)
| otherwise = []
r _ = []
The first counts from the left straight up, potentially stopping assembling the prefix in the middle of the full list traversal that it does carry to the end nevertheless, being a left fold.
The second also traverses the list in full turning it into a right fold which then gets to work counting down from the left again, being able to actually stop working as soon as the prefix is assembled.
Implementing drop this way is bound to be (?) even clunkier. Could be a nice exercise.
I note that you never specified the fold had to be over the supplied list. So, one approach that meets the letter of your question, though probably not the spirit, is:
sillytake :: Int -> [a] -> [a]
sillytake n xs = foldl go (const []) [1..n] xs
where go f _ (x:xs) = x : f xs
go _ _ [] = []
sillydrop :: Int -> [a] -> [a]
sillydrop n xs = foldl go id [1..n] xs
where go f _ (_:xs) = f xs
go _ _ [] = []
These each use left folds, but over the list of numbers [1..n] -- the numbers themselves are ignored, and the list is just used for its length to build a custom take n or drop n function for the given n. This function is then applied to the original supplied list xs.
These versions work fine on infinite lists:
> sillytake 5 $ sillydrop 5 $ [1..]
[6,7,8,9,10]
Will Ness showed a nice way to implement take with foldr. The least repulsive way to implement drop with foldr is this:
drop n0 xs0 = foldr go stop xs0 n0
where
stop _ = []
go x r n
| n <= 0 = x : r 0
| otherwise = r (n - 1)
Take the efficiency loss and rebuild the whole list if you have no choice! Better to drive a nail in with a screwdriver than drive a screw in with a hammer.
Both ways are horrible. But this one helps you understand how folds can be used to structure functions and what their limits are.
Folds just aren't the right tools for implementing drop; a paramorphism is the right tool.
You are not too far. Here are a pair of fixes.
First, note that func is passed the accumulator first (i.e. a list of a, in your case) and then the list element (an a). So, you need to swap the order of the arguments of func.
Then, if we want to mimic take, we need to add x when the length y is less than n, not greater!
So we get
myFunc :: Int -> [a] -> [a]
myFunc n list = foldl func [] list
where
func y x | (length y) < n = x : y
| otherwise = y
Test:
> myFunc 5 [1..10]
[5,4,3,2,1]
As you can see, this is reversing the string. This is because we add x at the front (x:y) instead of at the back (y++[x]). Or, alternatively, one could use reverse (foldl ....) to fix the order at the end.
Also, since foldl always scans the whole input list, myFunc 3 [1..1000000000] will take a lot of time, and myFunc 3 [1..] will fail to terminate. Using foldr would be much better.
drop is more tricky to do. I don't think you can easily do that without some post-processing like myFunc n xs = fst (foldl ...) or making foldl return a function which you immediately call (which is also a kind of post-processing).

Get index of next smallest element in the list in Haskell

I m a newbie to Haskell. I am pretty good with Imperative languages but not with functional. Haskell is my first as a functional language.
I am trying to figure out, how to get the index of the smallest element in the list where the minimum element is defined by me.
Let me explain by examples.
For example :
Function signature
minList :: x -> [x]
let x = 2
let list = [2,3,5,4,6,5,2,1,7,9,2]
minList x list --output 1 <- is index
This should return 1. Because the at list[1] is 3. It returns 1 because 3 is the smallest element after x (=2).
let x = 1
let list = [3,5,4,6,5,2,1,7,9,2]
minList x list -- output 9 <- is index
It should return 9 because at list[9] is 2 and 2 is the smallest element after 1. x = 1 which is defined by me.
What I have tried so far.
minListIndex :: (Ord a, Num a) => a -> [a] -> a
minListIndex x [] = 0
minListIndex x (y:ys)
| x > y = length ys
| otherwise = m
where m = minListIndex x ys
When I load the file I get this error
• Couldn't match expected type ‘a’ with actual type ‘Int’
‘a’ is a rigid type variable bound by
the type signature for:
minListIndex :: forall a. (Ord a, Num a) => a -> [a] -> a
at myFile.hs:36:17
• In the expression: 1 + length ys
In an equation for ‘minListIndex’:
minListIndex x (y : ys)
| x > y = 1 + length ys
| otherwise = 1 + m
where
m = minListIndex x ys
• Relevant bindings include
m :: a (bound at myFile.hs:41:19)
ys :: [a] (bound at myFile.hs:38:19)
y :: a (bound at myFile.hs:38:17)
x :: a (bound at myFile.hs:38:14)
minListIndex :: a -> [a] -> a (bound at myFile.hs:37:1)
When I modify the function like this
minListIndex :: (Ord a, Num a) => a -> [a] -> a
minListIndex x [] = 0
minListIndex x (y:ys)
| x > y = 2 -- <- modified...
| otherwise = 3 -- <- modifiedd
where m = minListIndex x ys
I load the file again then it compiles and runs but ofc the output is not desired.
What is the problem with
| x > y = length ys
| otherwise = m
?
In short: Basically, I want to find the index of the smallest element but higher than the x which is defined by me in parameter/function signature.
Thanks for the help in advance!
minListIndex :: (Ord a, Num a) => a -> [a] -> a
The problem is that you are trying to return result of generic type a but it is actually index in a list.
Suppose you are trying to evaluate your function for a list of doubles. In this case compiler should instantiate function's type to Double -> [Double] -> Double which is nonsense.
Actually compiler notices that you are returning something that is derived from list's length and warns you that it is not possible to match generic type a with concrete Int.
length ys returns Int, so you can try this instead:
minListIndex :: Ord a => a -> [a] -> Int
Regarding your original problem, seems that you can't solve it with plain recursion. Consider defining helper recursive function with accumulator. In your case it can be a pair (min_value_so_far, its_index).
First off, I'd separate the index type from the list element type altogether. There's no apparent reason for them to be the same. I will use the BangPatterns extension to avoid a space leak without too much notation; enable that by adding {-# language BangPatterns #-} to the very top of the file. I will also import Data.Word to get access to the Word64 type.
There are two stages: first, find the index of the given element (if it's present) and the rest of the list beyond that point. Then, find the index of the minimum of the tail.
-- Find the 0-based index of the first occurrence
-- of the given element in the list, and
-- the rest of the list after that element.
findGiven :: Eq a => a -> [a] -> Maybe (Word64, [a])
findGiven given = go 0 where
go !_k [] = Nothing --not found
go !k (x:xs)
| given == xs = Just (k, xs)
| otherwise = go (k+1) xs
-- Find the minimum (and its index) of the elements of the
-- list greater than the given one.
findMinWithIndexOver :: Ord a => a -> [a] -> Maybe (Word64, a)
findMinWithIndexOver given = go 0 Nothing where
go !_k acc [] = acc
go !k acc (x : xs)
| x <= given = go (k + 1) acc xs
| otherwise
= case acc of
Nothing -> go (k + 1) (Just (k, x)) xs
Just (ix_min, curr_min)
| x < ix_min = go (k + 1) (Just (k, x)) xs
| otherwise = go (k + 1) acc xs
You can now put these functions together to construct the one you seek. If you want a general Num result rather than a Word64 one, you can use fromIntegral at the very end. Why use Word64? Unlike Int or Word, it's (practically) guaranteed not to overflow in any reasonable amount of time. It's likely substantially faster than using something like Integer or Natural directly.
It is not clear for me what do you want exactly. Based on examples I guess it is: find the index of the smallest element higher than x which appears after x. In that case, This solution is plain Prelude. No imports
minList :: Ord a => a -> [a] -> Int
minList x l = snd . minimum . filter (\a -> x < fst a) . dropWhile (\a -> x /= fst a) $ zip l [0..]
The logic is:
create the list of pairs, [(elem, index)] using zip l [0..]
drop elements until you find the input x using dropWhile (\a -> x /= fst a)
discards elements less than x using filter (\a -> x < fst a)
find the minimum of the resulting list. Tuples are ordered using lexicographic order so it fits your problem
take the index using snd
Your function can be constructed out of ready-made parts as
import Data.Maybe (listToMaybe)
import Data.List (sortBy)
import Data.Ord (comparing)
foo :: (Ord a, Enum b) => a -> [a] -> Maybe b
foo x = fmap fst . listToMaybe . take 1
. dropWhile ((<= x) . snd)
. sortBy (comparing snd)
. dropWhile ((/= x) . snd)
. zip [toEnum 0..]
This Maybe finds the index of the next smallest element in the list above the given element, situated after the given element, in the input list. As you've requested.
You can use any Enum type of your choosing as the index.
Now you can implement this higher-level executable specs as direct recursion, using an efficient Map data structure to hold your sorted elements above x seen so far to find the next smallest, etc.
Correctness first, efficiency later!
Efficiency update: dropping after the sort drops them sorted, so there's a wasted effort there; indeed it should be replaced with the filtering (as seen in the answer by Luis Morillo) before the sort. And if our element type is in Integral (so it is a properly discrete type, unlike just an Enum, thanks to #dfeuer for pointing this out!), there's one more opportunity for an opportunistic optimization: if we hit on a succ minimal element by pure chance, there's no further chance of improvement, and so we should bail out at that point right there:
bar :: (Integral a, Enum b) => a -> [a] -> Maybe b
bar x = fmap fst . either Just (listToMaybe . take 1
. sortBy (comparing snd))
. findOrFilter ((== succ x).snd) ((> x).snd)
. dropWhile ((/= x) . snd)
. zip [toEnum 0..]
findOrFilter :: (a -> Bool) -> (a -> Bool) -> [a] -> Either a [a]
findOrFilter t p = go
where go [] = Right []
go (x:xs) | t x = Left x
| otherwise = fmap ([x | p x] ++) $ go xs
Testing:
> foo 5 [2,3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 4
> foo 2 [2,3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 1
> foo 1 [3,5,4,6,5,2,1,7,9,2] :: Maybe Int
Just 9

Edit every Nth item in a list

I want to perform an arithmetic operation (e.g. doubling the value) on a list of integers, every n places.
For example, given the list [1,2,3,4,5,6,7], I want to double values every three places. In that case, we would have [1,2,6,4,5,12,7].
How can I do it?
applyEvery :: Int -> (a -> a) -> [a] -> [a]
applyEvery n f = zipWith ($) (cycle (replicate (n-1) id ++ [f]))
The cycle subexpression builds a list of functions [id,id,...,id,f] with the correct number of elements and repeats it ad nauseam, while the zipWith ($) applies that list of functions to the argument list.
Since you asked for it, more detail! Feel free to ask for more explanation.
The main idea is maybe best explained with an ASCII picture (which won't stop me from writing a thousand a lot of ASCII words!):
functions : [ id, id, f , id, id, f , id, id, f, ...
input list: [ 1, 2, 3, 4, 5, 6, 7 ]
-----------------------------------------------------
result : [ 1, 2, f 3, 4, 5, f 6, 7 ]
Just like there's no reason to hardcode the fact that you want to double every third element in the list, there's nothing special about f (which in your example is doubling), except that it should have the same result type as doing nothing. So I made these the parameters of my function. It's even not important that you operate on a list of numbers, so the function works on lists of a, as long as it's given an 'interval' and an operation. That gives us the type signature applyEvery :: Int -> (a -> a) -> [a] -> [a]. I put the input list last, because then a partial application like doubleEveryThird = applyEvery 3 (*2) is something that returns a new list, a so-called combinator. I picked the order of the other two arguments basically at random :-)
To build the list of functions, we first assemble the basic building block, consisting of n-1 ids, followed by an f as follows: replicate (n-1) id ++ [f]. replicate m x makes a list containing m repetitions of the xargument, e.g. replicate 5 'a' = "aaaaa", but it also works for functions. We have to append the f wrapped in a list of its own, instead of using : because you can only prepend single elements at the front - Haskell's lists are singly-linked.
Next, we keep on repeating the basic building block with cycle (not repeat as I first had mistakenly). cycle has type [a] -> [a] so the result is a list of "the same level of nested-ness". Example cycle [1,2,3] evaluates to [1,2,3,1,2,3,1,2,3,...]
[ Side note: the only repeat-y function we haven't used is repeat itself: that forms an infinite list consisting of its argument ]
With that out of the way, the slightly tricky zipWith ($) part. You might already know the plain zip function, which takes two lists and puts elements in the same place in a tuple in the result, terminating when either list runs out of elements. Pictorially:
xs : [ a , b , c , d, e]
ys: [ x, y , z ]
------------------------------
zip xs ys: [(a,x),(b,y),(c,z)]
This already looks an awful lot like the first picture, right? The only thing is that we don't want to put the individual elements together in a tuple, but apply the first element (which is a function) to the second instead. Zipping with a custom combining function is done with zipWith. Another picture (the last one, I promise!):
xs : [ a , b , c , d, e]
ys: [ x, y, z ]
----------------------------------------
zipWith f xs ys: [ f a x, f b y, f c z ]
Now, what should we choose to zipWith with? Well, we want to apply the first argument to the second, so (\f x -> f x) should do the trick. If lambdas make you uncomfortable, you can also define a top-level function apply f x = f x and use that instead. However, this already a standard operator in the Prelude, namely $! Since you can't use a infix operator as a standalone function, we have to use the syntactic sugar ($) (which really just means (\f x -> f $ x))
Putting all of the above together, we get:
applyEvery :: Int -> (a -> a) -> [a] -> [a]
applyEvery n f xs = zipWith ($) (cycle (replicate (n-1) id ++ [f])) xs
But we can get rid of the xs at the end, leading to the definition I gave.
A common way to get indexes for values in a list is to zip the list into tuples of (value, index).
ghci > let zipped = zip [1,2,3,4,5,6,7] [1..]
ghci > zipped
[(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7)]
Then you just need to map over that list and return a new one. If index is divisible by 3 (index `rem` 3 == 0), we'll double the value, otherwise we'll return the same value:
ghci > map (\(value, index) -> if index `rem` 3 == 0 then value*2 else value) zipped
[1,2,6,4,5,12,7]
Tell me if that all makes sense—I can add more detail if you aren't familiar with zip and map and such.
Zip
You can find documentation on zip by looking at its Haddocks, which say: "zip takes two lists and returns a list of corresponding pairs." (Docs are hosted in several places, but I went to https://www.stackage.org and searched for zip).
Map
The map function applies a function to each item in a list, generating a new value for each element.
Lambdas
Lambdas are just functions without a specific name. We used one in the first argument to map to say what we should do to each element in the list. You may have seen these in other languages like Python, Ruby, or Swift.
This is the syntax for lambdas:
(\arg1, arg2 -> functionBodyHere)
We could have also written it without a lambda:
ghci > let myCalculation (value, index) = if index `rem` 3 == 0 then value*2 else value
ghci > map myCalculation zipped
[1,2,6,4,5,12,7]
Note: this code is not yet tested.
In lens land, this is called a Traversal. Control.Lens gives you these:
{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
type Traversal s t a b =
forall f . Applicative f => (a -> f b) -> s -> f t
type Traversal' s a = Traversal s s a a
We can use lens's itraverse from Control.Lens.Indexed:
-- everyNth :: (TraversableWithIndex i t, Integral i)
=> i -> Traversal' (t a) a
everyNth :: (TraversableWithIndex i t, Integral i, Applicative f)
=> i -> (a -> f a) -> t a -> f (t a)
everyNth n f = itraverse f where
g i x | i `rem` n == n - 1 = f x
| otherwise = pure x
This can be specialized to your specific purpose:
import Data.Profunctor.Unsafe
import Data.Functor.Identity
everyNthPureList :: Int -> (a -> a) -> [a] -> [a]
everyNthPureList n f = runIdentity #. everyNth n (Identity #. f)
mapIf :: (Int -> Bool) -> (a -> a) -> [a] -> [a]
mapIf pred f l = map (\(value,index) -> if (pred index) then f value else value) $ zip l [1..]
mapEveryN :: Int -> (a -> a) -> [a] -> [a]
mapEveryN n = mapIf (\x -> x `mod` n == 0)
Live on Ideone.
A simple recursive approach:
everyNth n f xs = igo n xs where
igo 1 (y:ys) = f y : igo n ys
igo m (y:ys) = y : igo (m-1) ys
igo _ [] = []
doubleEveryThird = everyNth 3 (*2)
Basically, igo starts at n, counts down until it reaches 1, where it will apply the function, and go back up to n. doubleEveryThird is partially applied: everyNth expects three arguments, but we only gave it two, so dougleEveryThird will expect that final argument.

Haskell: How to simplify or eliminate liftM2?

Consider the following code I wrote:
import Control.Monad
increasing :: Integer -> [Integer]
increasing n
| n == 1 = [1..9]
| otherwise = do let ps = increasing (n - 1)
let last = liftM2 mod ps [10]
let next = liftM2 (*) ps [10]
alternateEndings next last
where alternateEndings xs ys = concat $ zipWith alts xs ys
alts x y = liftM2 (+) [x] [y..9]
Where 'increasing n' should return a list of n-digit numbers whose numbers increase (or stay the same) from left-to-right.
Is there a way to simplify this? The use of 'let' and 'liftM2' everywhere looks ugly to me. I think I'm missing something vital about the list monad, but I can't seem to get rid of them.
Well, as far as liftM functions go, my preferred way to use those is the combinators defined in Control.Applicative. Using those, you'd be able to write last = mod <$> ps <*> [10]. The ap function from Control.Monad does the same thing, but I prefer the infix version.
What (<$>) and (<*>) goes like this: liftM2 turns a function a -> b -> c into a function m a -> m b -> m c. Plain liftM is just (a -> b) -> (m a -> m b), which is the same as fmap and also (<$>).
What happens if you do that to a multi-argument function? It turns something like a -> b -> c -> d into m a -> m (b -> c -> d). This is where ap or (<*>) come in: what they do is turn something like m (a -> b) into m a -> m b. So you can keep stringing it along that way for as many arguments as you like.
That said, Travis Brown is correct that, in this case, it seems you don't really need any of the above. In fact, you can simplify your function a great deal: For instance, both last and next can be written as single-argument functions mapped over the same list, ps, and zipWith is the same as a zip and a map. All of these maps can be combined and pushed down into the alts function. This makes alts a single-argument function, eliminating the zip as well. Finally, the concat can be combined with the map as concatMap or, if preferred, (>>=). Here's what it ends up:
increasing' :: Integer -> [Integer]
increasing' 1 = [1..9]
increasing' n = increasing' (n - 1) >>= alts
where alts x = map ((x * 10) +) [mod x 10..9]
Note that all refactoring I did to get to that version from yours was purely syntactic, only applying transformations that should have no impact on the result of the function. Equational reasoning and referential transparency are nice!
I think what you are trying to do is this:
increasing :: Integer -> [Integer]
increasing 1 = [1..9]
increasing n = do p <- increasing (n - 1)
let last = p `mod` 10
next = p * 10
alt <- [last .. 9]
return $ next + alt
Or, using a "list comprehension", which is just special monad syntax for lists:
increasing2 :: Integer -> [Integer]
increasing2 1 = [1..9]
increasing2 n = [next + alt | p <- increasing (n - 1),
let last = p `mod` 10
next = p * 10,
alt <- [last .. 9]
]
The idea in the list monad is that you use "bind" (<-) to iterate over a list of values, and let to compute a single value based on what you have so far in the current iteration. When you use bind a second time, the iterations are nested from that point on.
It looks very unusual to me to use liftM2 (or <$> and <*>) when one of the arguments is always a singleton list. Why not just use map? The following does the same thing as your code:
increasing :: Integer -> [Integer]
increasing n
| n == 1 = [1..9]
| otherwise = do let ps = increasing (n - 1)
let last = map (flip mod 10) ps
let next = map (10 *) ps
alternateEndings next last
where alternateEndings xs ys = concat $ zipWith alts xs ys
alts x y = map (x +) [y..9]
Here's how I'd write your code:
increasing :: Integer -> [Integer]
increasing 1 = [1..9]
increasing n = let allEndings x = map (10*x +) [x `mod` 10 .. 9]
in concatMap allEndings $ increasing (n - 1)
I arrived at this code as follows. The first thing I did was to use pattern matching instead of guards, since it's clearer here. The next thing I did was to eliminate the liftM2s. They're unnecessary here, because they're always called with one size-one list; in that case, it's the same as calling map. So liftM2 (*) ps [10] is just map (* 10) ps, and similarly for the other call sites. If you want a general replacement for liftM2, though, you can use Control.Applicative's <$> (which is just fmap) and <*> to replace liftMn for any n: liftMn f a b c ... z becomes f <$> a <*> b <*> c <*> ... <*> z. Whether or not it's nicer is a matter of taste; I happen to like it.1 But here, we can eliminate that entirely.
The next place I simplified the original code is the do .... You never actually take advantage of the fact that you're in a do-block, and so that code can become
let ps = increasing (n - 1)
last = map (`mod` 10) ps
next = map (* 10) ps
in alternateEndings next last
From here, arriving at my code essentially involved writing fusing all of your maps together. One of the only remaining calls that wasn't a map was zipWith. But because you effectively have zipWith alts next last, you only work with 10*p and p `mod` 10 at the same time, so we can calculate them in the same function. This leads to
let ps = increasing (n - 1)
in concat $ map alts ps
where alts p = map (10*p +) [y `mod` 10..9]
And this is basically my code: concat $ map ... should always become concatMap (which, incidentally, is =<< in the list monad), we only use ps once so we can fold it in, and I prefer let to where.
1: Technically, this only works for Applicatives, so if you happen to be using a monad which hasn't been made one, <$> is `liftM` and <*> is `ap`. All monads can be made applicative functors, though, and many of them have been.
I think it's cleaner to pass last digit in a separate parameter and use lists.
f a 0 = [[]]
f a n = do x <- [a..9]
k <- f x (n-1)
return (x:k)
num = foldl (\x y -> 10*x + y) 0
increasing = map num . f 1