Merging Two Lists of Tuples - list

I need to create a recursive function that merges two lists of tuples together and it starts with a known tuple. The function receives three parameters:
two lists of tuples
a tuple
I've tried this:
mergePoints l1 l2 o = o ++ [f | (a, b) <- zip l1 l2,
let f if a < b then f = a, b else f = b, a]
I know I'm not doing it right, but I really don't know how to do it.
The example input and output for the exercise is:
ghci> mergePoints [(1, 3), (1, 4), (5, 5)] [(1, 1), (4, 4)] (0, 0)
[(0.0, 0.0), (1.0, 1.0), (1.0, 3.0), (1.0, 4.0), (4.0, 4.0), (5.0, 5.0)]

According to your example,
ghci> mergePoints [(1, 3), (1, 4), (5, 5)] [(1, 1), (4, 4)]
(0, 0)
[ (0.0, 0.0), (1.0, 1.0),
(1.0, 3.0), (1.0, 4.0), (4.0, 4.0),
(5.0, 5.0)]
each of the two lists is consumed at its own pace, so zip won't fit here, as it consumes its argument lists at the same pace.
The simplest way to code this is with a directly recursive definition with pattern matching that will compare the two head elements and use one or the other, depending on the result of the comparison.
Perhaps you will also need to compare them with the supplied third point, in case it's not the smallest.
So, about your code.
Judging from the example input and output, the points are supposed to come out in order. We can just compare the tuples as they define a lexicographical ordering. You already are doing that. With a small syntactical fix your code is:
mergePoints1 l1 l2 o = o ++ [f | (a, b) <- zip l1 l2,
let f if a < b then f = [a, b]
else f = [b, a]]
This is not a valid Haskell. There is no assignment in Haskell, only definition:
mergePoints2 l1 l2 o = o ++ [f | (a, b) <- zip l1 l2,
let f = if a < b then [a, b] else [b, a]]
But this list comprehension creates a list of lists of tuples, as we're creating them as either f = [a,b] or f = [b,a]. Using the points one by one we need to "draw" them from those short lists, one by one, with
mergePoints3 l1 l2 o = o ++ [r | (a, b) <- zip l1 l2,
r <- if a < b then [a, b] else [b, a]]
(using r for "result", instead of f). The last error is that ++ concatenates two lists, but o isn't one. So then it must be
mergePoints4 l1 l2 o = [o] ++ merge1 l1 l2
merge1 l1 l2 = [r | (a, b) <- zip l1 l2,
r <- if a < b then [a, b] else [b, a]]
Now it works, but doesn't do what it's supposed to. And in fact, since its output is still not guaranteed to be ordered, we could even just write this as
merge2 l1 l2 = l1 ++ l2
where -- the definition of the built-in `++`:
[] ++ l2 = l2
l1 ++ [] = l1
(x:t1) ++ l2 = x : (t1 ++ l2)
or we could pull the elements from both lists with
merge3 l1 l2 = l1 ++ l2
where
[] ++ l2 = l2
l1 ++ [] = l1
(x:t1) ++ (y:t2) = x : y : (t1 ++ t2) -- or:
-- = x : ((y:t2) ++ t1)
Of course taking out the elements one by one positionally scrambles up their ordering, potentially. Your attempt to rectify this with the merge1 can be re-written as
merge1b l1 l2 = l1 ++ l2
where
[] ++ l2 = l2
l1 ++ [] = l1
(x:t1) ++ (y:t2) = if x < y then x : y : (t1 ++ t2)
else y : x : (t1 ++ t2)
but it still can scramble up the order. We assume our two inputs to be ordered, increasing lists where each element is smaller then the one that follows it in the list. So we just need to use that knowledge, carefully pulling just one of the elements:
merge4 l1 l2 = l1 ++ l2
where
[] ++ l2 = l2
l1 ++ [] = l1
(x:t1) ++ (y:t2) = if x < y then x : (_ ++ (y:t2))
else _ : _
You need to complete this definition by replacing the _s with the actual code.
Bonus question: the usual definition of merge in Haskell prefers its "left" argument over the "right" one, in case of equality of the two elements. Make a one-character edit to the code, to achieve this.

Related

OCaml split function

I'm currently studying for a CS exam and I'm having an hard time understanding an exercise from my book. The exercise is as follows:
Define, using FOLDR and without using explicit recursion, a function (split : ’a list -> ’a -> ’a list * ’a list) such that split l n returns a pair of lists. The first contains all the values preceding the first occurrence of n in l (in the same order), and the second contains all the remaining elements (in the same order). If n does not appear in l, there are no values preceding the first occurrence of n.
Examples: split [3;-5;1;0;1;-8;0;3] 0 = ([3;-5;1],[0;1;-8;0;3]), split [3;4;5] 7 = ([],[3;4;5])
This is the code written by my professor to solve the exercise:
let split l n =
let f x (l1, l2, b) =
if x = n then ([], x::(l1#l2), true)
else if b then (x::l1, l2, b)
else (l1, x::l2, b)
in let (l1, l2, b) = foldr f ([], [], false) l in (l1, l2) ;;
I don’t understand that second line at all (let f x (l1, l2, b)).
How do those parameters get filled with a value, so that all the logic that comes with it makes sense? For example: what is x and how can it be compared to n if it has no value? What is the meaning of those Boolean values in b?
In addition I don't understand that foldr function in the last line and I don't find any documentation about it. In fact, even my compiler doesn’t understand what foldr is and gives me an error (*Unbound value foldr*). Initially I thought it was some kind of abbreviation for List.fold_right but if I try to replace with the latter I still get an error because the following parameters are not correct (File "split.ml", line 6, characters 41-56:
Error: This expression has type 'a * 'b * 'c
but an expression was expected of type 'd list).
Thank you in advance for any help or advice.
I don't know whether this is allowed by OCAML's syntax rules or not, but let's add some extra white space to make it clearer:
let split l n =
let f x ( l1, l2 , b ) =
if x = n then ( [], x::(l1#l2), true )
else if b then (x::l1, l2 , b ) (* b is true *)
else ( l1, x:: l2 , b ) (* b is false *)
in let (l1, l2, b) = foldr f ( [], [] , false) l
in (l1, l2) ;;
foldr is, in pseudocode,
foldr f z [x1 ; x2 ; ... ; xn1 ; xn ]
=
x1 -f- (x2 -f- (... -f- (xn1 -f- (xn -f- z))...))
where a -f- b denotes simple application f a b, just written infix for convenience. In other words,
foldr f z [x1 ; x2 ; ... ; xn1 ; xn] (* x_{n-1} *)
=
f x1 (foldr f z [x2 ; ... ; xn1 ; xn]) (* x_{n-1} *)
whereas
foldr f z [] = z
Thus the above is actually equivalent to
= let t1 = f xn z
in let t2 = f xn1 t1 (* x_{n-1} *)
in ....
in let tn1 = f x2 tn2 (* t_{n-2} *)
in let tn = f x1 tn1 (* t_{n-1} *)
in tn
You should now be able to see that what this does is to work on the list's elements from right to left, passing interim results to the subsequent applications of f on the left.
You should also be able now to write that missing definition of foldr yourself.
So if we substitute your specific definition of f, how it works for a list of e.g. three elements [x1; x2; x3] where x2 = n, is equivalent to
let (l1, l2, b ) = ( [], [] , false)
in let (l1_3, l2_3, b_3) = ( l1, x3::l2 , b )
in let (l1_2, l2_2, b_2) = ( [], x2::(l1_3#l2_3) , true )
in let (l1_1, l2_1, b_1) = (x1::l1_2, l2_2 , b_2 )
in (l1_1, l2_1)
i.e.
let (l1, l2, b ) = ( [], [] , false)
in let (l1_3, l2_3, b_3) = ( [], x3::[] , false)
in let (l1_2, l2_2, b_2) = ( [], x2::([]#[x3]) , true )
in let (l1_1, l2_1, b_1) = (x1::[], [x2 ; x3] , true )
in ([x1], [x2; x3])
Thus the resulting lists are being built from the back.
The Boolean flags being passed along allows the function to correctly handle cases where there are more than one elements equal to n in the list. The same effect can be achieved without any flags, with a small post-processing step instead, as
let split l n =
let f x ( l1, l2 ) =
if x = n then ( [], x::(l1#l2))
else (x::l1, l2 )
in match foldr f ( [], [] ) l with
| (l1, []) -> ([], l1)
| (l1, l2) -> (l1, l2) ;;
(if that's not a valid OCaml code, take it as a pseudocode then).
If you use the List.fold_right then this will work.
let split l n =
let f x (l1, l2, b) =
if x = n
then
([], x::(l1#l2), true)
else if b
then
(x::l1, l2, b)
else
(l1, x::l2, b)
in let (l1, l2, b) = List.fold_right f l ([], [], false)
in (l1, l2)
Fellow CS Major here.
let f x (l1, l2, b)
defines a function, which takes two arguments one called x and one is a tripple of 3 arguments (l1, l2, b). This function has it's scope limited to the following line
in let (l1, l2, b) = foldr f ([], [], false) l in (l1, l2) ;;
The part you are probably struggling with is the keyword "in" which limits the scope of one expression to the next one. so exp1 in exp2 limits the scope of expression one to expression two.
Also, x and (l1, l2, b) stand for arbitrary parameters only valid in the function body. Look at which parameters foldr takes (the first one should be a function that has the same parameters as the function f your professor defined). This foldr function then assigns a value to x (and (l1, l2, b)) in the context of foldr.
let f x (l1, l2, b)
....
in let (l1, l2, b) = foldr f ([], [], false) l in (l1, l2) ;;
While (l1, l2, b) in the first line is not the same as (l1, l2, b) in the third line (of the snippet above), here
in let (l1, l2, b) = foldr f ([], [], false) l in (l1, l2) ;;
l1 and l2 are the same (in let (l1, l2, b) and in (l1, l2)).
PS: You need to define the foldr function (either import it or maybe your professor has some definition on the exercise sheet that you can copy).

Testing diagonally adjacent elements in nested lists

This is a followup to a recent question that wasn't asked clearly. The poster Aditi Jain's clarifications invalidate the answer somewhat that's already posted there, hence this new post.
The objective is to check whether there's no diagonally adjacent pair of elements in the nested lists which are negative of one another. The poster is new to Haskell programming.
The function signature is:
checkNegation :: [[Int]] -> Bool
Examples:
checkNegation [[1,2], [-2,3]] will return False:
[ [ 1 , 2], -- 2, -2 are diagonally adjacent
[-2 , 3] ]
checkNegation [[1,2], [3,-1]] will return False:
[ [ 1 , 2], -- 1, -1 are diagonally adjacent
[ 3 , -1] ]
checkNegation [[1,2], [-1,3]] will return True:
[ [ 1 , 2], -- no diagonally adjacent negatives
[-1 , 3] ]
checkNegation [[0,2,1], [3,1,-2], [3,-1,3]] will return False:
[ [ 0 , 2, 1], -- 2, -2 are diagonally adjacent
[ 3 , 1, -2],
[ 3 , -1, 3] ]
No coding attempts were provided in the original post.
(I'm not marking this as CW so as not to prevent the answerers getting reputation points for their efforts)
It's a little easier to do things if we take the matrix row-by-row. For the following, for instance:
[a,b,c],
[d,e,f],
We only want to compare the pairs:
[(a,e),(b,f),(b,d),(c,e)]
So the first step is to write a function which constructs that list from two adjacent rows.
diags xs ys = zip xs (drop 1 ys) ++ zip (drop 1 xs) ys
We're using drop 1 rather than tail because it doesn't error on the empty list, and the way I'm going to use this function later will use empty lists.
If we use this in a fold, then, it looks like the following:
anyDiags :: (a -> a -> Bool) -> [[a]] -> Bool
anyDiags p = fst . foldr f (False, [])
where
f xs (a, ys) = (a || or (zipWith p xs (drop 1 ys)) || or (zipWith p (drop 1 xs) ys), xs)
We've also made it generic over any relation.
Next we will want to figure out how to check if two numbers are negations of each other.
negEachOther x y = negate x == y
And then our check negation function is as follows:
checkNegation = anyDiags negEachOther
There are some fun things we can do with the anyDiags function here. There's actually a use of the writer monad hidden in it. With that, we can rewrite the fold to use that fact:
anyDiags :: (a -> a -> Bool) -> [[a]] -> Bool
anyDiags p = getAny . fst . foldrM f []
where
f xs ys = (Any (or (zipWith p xs (drop 1 ys)) || or (zipWith p (drop 1 xs) ys)), xs)
Though I'm not sure if it's any clearer.
Alternatively, we could do the whole thing using the zip xs (tail xs) trick:
anyDiags :: (a -> a -> Bool) -> [[a]] -> Bool
anyDiags p xs = or (zipWith f xs (tail xs))
where
f xs ys = or (zipWith p xs (drop 1 ys)) || or (zipWith p (drop 1 xs) ys)
We can use the diagonals utility from Data.Universe.Helpers package. Such that
λ> diagonals [[0,2,1], [3,1,-2], [3,-1,3]]
[[0],[3,2],[3,1,1],[-1,-2],[3]]
which is only half of what we need. So lets flip our 2D list and apply diagonals once more. Flipping a list would take reverse . transpose operation such that
λ> (reverse . transpose) [[0,2,1], [3,1,-2], [3,-1,3]]
[[1,-2,3],[2,1,-1],[0,3,3]]
now we can use diagonals on this flipped list to obtain the remaining diagonals.
λ> (diagonals . reverse . transpose) [[0,2,1], [3,1,-2], [3,-1,3]]
[[1],[2,-2],[0,1,3],[3,-1],[3]]
For all diagonals we need to concatenate them. So altogether we may do like;
allDiags = (++) <$> diagonals . reverse . transpose <*> diagonals
The rest is applying necessary boolean test.
import Data.List (transpose)
import Data.Universe.Helpers (diagonals)
checkNegation :: Num a => Eq a => [[a]] -> Bool
checkNegation = and . map (and . (zipWith (\x y -> 0 /= (x + y)) <*> tail)) . allDiags
where
allDiags = (++) <$> diagonals . reverse . transpose <*> diagonals
λ> checkNegation [[0,2,1], [3,1,-2], [3,-1,3]]
False
λ> checkNegation [[1,2], [-1,3]]
True
If you have a matrix like this and want to compare adjacent diagonal elements:
m = [[ 1, 2, 3, 4]
,[ 5, 6, 7, 8]
,[ 9,10,11,12]]
then you want to make two comparisons. First, you want to compare, element by element, the sub-matrix you get by dropping the first row and first column (left) with the sub-matrix you get by dropping the last row and last column (right):
[[ 6, 7, 8] [[ 1, 2, 3]
,[10,11,12] ,[ 5, 6, 7]]
Second, you want to compare, element by element, the sub-matrix you get by dropping the first row and last column (left) with the sub-matrix you get by dropping the last row and first column (right):
[[ 5, 6, 7] [[ 2, 3, 4]
,[ 9,10,11]] ,[ 6, 7, 8]]
We can construct these submatrices using init, tail, and maps of these:
m1 = tail (map tail m) -- drop first row and first column
m2 = init (map init m) -- drop last row and last column
m3 = tail (map init m) -- drop first row and last column
m4 = init (map tail m) -- drop last row and first column
giving:
λ> m1
[[6,7,8],[10,11,12]]
λ> m2
[[1,2,3],[5,6,7]]
λ> m3
[[5,6,7],[9,10,11]]
λ> m4
[[2,3,4],[6,7,8]]
How do we compare two sub-matrices? Well, we can write a two-dimensional version of zipWith to apply a binary function (a comparison, say) element by element to two matrices, the same way zipWith applies a binary function element by element to two lists:
zipZipWith :: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
zipZipWith f m1 m2 = zipWith zipRow m1 m2
where zipRow r1 r2 = zipWith f r1 r2
This works by zipping the matrices together, row by row, using the zipRow helper function. For each pair of rows, zipRow zips the rows together, element by element, with the function f. This definition can be simplified to the slightly less clear:
zipZipWith f m1 m2 = zipWith (zipWith f) m1 m2
Anyway, to check if corresponding pairs of elements in two matrices are negatives of each other, we can use zipZipWith isNeg where:
isNeg :: (Num a, Eq a) => a -> a -> Bool
isNeg x y = x == -y
Then, to check if any of these pairs are negatives, we can use concat to change the matrix of booleans into a long list and or to check for any True values:
anyNegPairs :: (Num a, Eq a) => [[a]] -> [[a]] -> Bool
anyNegPairs ma mb = or . concat $ zipZipWith isNeg ma mb
Finally, then, a complete function to perform the comparison would be:
noDiagNeg :: (Num a, Eq a) => [[a]] -> Bool
noDiagNeg m = not (anyNegPairs m1 m2 || anyNegPairs m3 m4)
Since zipZipWith, like zipWith, ignores "extra" elements when comparing arguments of different sizes, it's not actually necessary to trim off the last column/row, so the sub-matrix definitions can be simplified by removing all the inits:
m1 = tail (map tail m)
m2 = m
m3 = tail m
m4 = map tail m
We could actually write m1 in terms of m4 to save double-calculating map tail m:
m1 = tail m4
but the compiler is smart enough to figure this out on its own.
So, a reasonable final solution would be:
noDiagNeg :: (Num a, Eq a) => [[a]] -> Bool
noDiagNeg m = not (anyNegPairs m1 m2 || anyNegPairs m3 m4)
where
m1 = tail (map tail m)
m2 = m
m3 = tail m
m4 = map tail m
anyNegPairs ma mb = or . concat $ zipZipWith isNeg ma mb
isNeg x y = x == -y
zipZipWith :: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
zipZipWith f m1 m2 = zipWith (zipWith f) m1 m2
and it seems to work as desired on the test cases:
λ> noDiagNeg [[1,2],[-2,3]]
False
λ> noDiagNeg [[1,2],[3,-1]]
False
λ> noDiagNeg [[1,2],[-1,3]]
True
λ> noDiagNeg [[0,2,1],[3,1,-2],[3,-1,3]]
False
This is quite similar to #oisdk's solution, though this version might be easier to understand if you aren't too familiar with folds yet.
It fails on (certain) matrices with no elements:
λ> noDiagNeg []
*** Exception: Prelude.tail: empty list
λ> noDiagNeg [[],[]]
*** Exception: Prelude.tail: empty list
so you could use #oisdk's technique of replacing tail with drop 1, if this is a problem. (Actually, I might define tail' = drop 1 as a helper and replace all tail calls with tail' calls, since that would look a little nicer.)
First we pair up the rows: first with second, then second with third, then third with fourth, and so on.
Then, for each pair of rows, we consider all wedge-shaped triples of cells, like this:
--*---
-*-*--
So that the bottom-row cells are diagonally adjacent to the top-row ones.
Then we just check if any of the bottom ones are a negative of the top.
Except this has (literally) an edge case: beginnings and ends of the rows. If we do this wedge-shaped triple thing, we're going to miss the first and the last elements of the top row. To get around this, we first wrap the whole matrix in Just and then extend each row with Nothings on left and right:
[a,b,c] ==> [Nothing, Just a, Just b, Just c, Nothing]
[d,e,f] ==> [Nothing, Just d, Just e, Just f, Nothing]
Now we can safely iterate in triples and not miss anything.
checkNegation :: [[Int]] -> Bool
checkNegation matrix = any rowPairHasNegation rowPairs
where
extendedMatrix = map extendRow matrix
extendRow row = [Nothing] ++ map Just row ++ [Nothing]
rowPairs = extendedMatrix `zip` drop 1 extendedMatrix
rowPairHasNegation (row, nextRow) =
any cellTripleHasNegation $
drop 1 row `zip` nextRow `zip` drop 2 nextRow
cellTripleHasNegation ((x1y0, x0y1), x2y1) =
isNegation x1y0 x0y1 || isNegation x1y0 x2y1
isNegation (Just a) (Just b) = a == -b
isNegation _ _ = False
As far as I understand, this will result in iterating over the whole matrix exactly thrice - once as top row and twice as bottom row, meaning O(n*m)

OCaml: Combination of elements in Lists, functional reasoning

I am back to coding in OCaml and I missed it so much. I missed it so much I completely lost my reasoning in this language and I hit a wall today.
What I want to do is the combination of elements between a set of n lists.
I decomposed the problem by first attempting the combination of elements between two list of arbitrary sizes.
Assume we have to lists: l1 = [1;2;3] and l2 = [10,20].
What I want to do is obtain the following list:
l_res = [10;20;20;40;30;60]
I know how to do this using loop structures, but I really want to solve this without them.
I tried the following:
let f l1 l2 =
List.map (fun y -> (List.map (fun x -> x * y) l1) l2
But this does not seem to work. The type I get is f : int list -> int list -> int list list but I want f : int list -> int list -> int list
I tried already many different approaches I feel I am over complicating.
What did I miss?
What you are missing is that List.map f [a; b; c] gives [f a; f b; f c] so what you'll get from your function will be
f [a; b; c] [d; e] = [[ad; ae]; [bd; be]; [cd; ce]]
but you want
f [a; b; c] [d; e] = [ad; ae; bd; be; cd; ce]
so you need to use an other iterator, i.e. :
let f l1 l2 =
let res = List.fold_left (fun acc x ->
List.fold_left (fun acc y -> (x * y) :: acc) acc l2
) [] l1 in
List.rev res
or to flatten your result :
val concat : 'a list list -> 'a list
Concatenate a list of lists. The elements of the argument are all
concatenated together (in the same order) to give the result. Not
tail-recursive (length of the argument + length of the longest
sub-list).
val flatten : 'a list list -> 'a list
Same as concat. Not tail-recursive (length of the argument + length of
the longest sub-list).
Some Core-flavoured answers:
open Core.Std
let f1 l1 l2 =
List.map (List.cartesian_product l1 l2) ~f:(fun (x, y) -> x * y)
let f2 l1 l2 =
List.concat_map l1 ~f:(fun x -> List.map l2 ~f:(fun y -> x * y))
let f4 l1 l2 =
let open List.Monad_infix in
l1 >>= fun x ->
l2 >>| fun y ->
x * y
The last answer explicitly (and arguably the two other answers implicitly) makes use of the list monad, which this is a textbook use case of. I couldn't find the list monad in Batteries, which is possibly not so surprising as it's much less widely used than (say) the option or result monads.
let f l1 l2 =
let multiply x = List.map (( * )x) l2 in
l1 |> List.map multiply
|> List.concat

Process Haskell list from right to left keeping origin order

Need increment every second item starting from the right in Haskell list but keeping origin order (e.g. reverse is not a case). For example:
f [1, 2, 3] -- [1, 3, 3]
f [1, 2, 3, 4] -- [2, 2, 4, 4]
I've tried something like a following:
fc ([]) = []
fc (x:[]) = [x]
fc (x:[y]) = [x+1,y]
fc( x:xs ) = fc [x] : ( fc xs ) -- this line is wrong
p.s. Obviously I could reverse (but prefer to understand original task) the list twice and apply something like:
helper (x:y:tail) = [x, y+1] ++ tail
fc x = reverse (helper (reverse x) )
The typical way to process a Haskell list from right to left would be to reverse it. Since you want to have the original order for the result, you would simply reverse again:
f1 = reverse . zipWith (+) (cycle [0,1]) . reverse
But if you really want to, you can have each recursive call return both the updated tail and a flag that indicates whether that position is even when counted from the end so you know whether to increase the element at that position or not:
f2 = snd . g
where
g [] = (False, [])
g (x:xs) = let (addOne, xs') = g xs
x' = if addOne then x + 1 else x
in (not addOne, x':xs')
We're basically mapping a function over the list, but this function requires an extra parameter that gets computed starting from the right end of the list. There's a standard function we can use:
import Data.List (mapAccumR)
f2' = snd . mapAccumR g False
where
g addOne x = (not addOne, if addOne then x + 1 else x)
I think a cleaner specification for what you want is that you increment even indicies if the length is even and odd indicies if the length is odd. For example, when indexing from zero, the list of length 3 resulted in index 1 being incremented. One way to do this is with the obvious two pass solution:
f xs = zipWith (+) (cycle sol) xs
where sol = map fromEnum [even len, odd len]
len = length xs
This can be done in one pass (without relying on the compiler fusion rules) by "tying the knot". For example (using manual recursive style as means of communication).
f2 xs = let (isEven, result) = go isEven xs in result
where
go _ [] = (True, [])
go e (x:xs) = let (ne,rest) = go (not e) xs
in (not ne, x+fromEnum e : rest)
This can be done efficiently using a left fold:
inc :: Num a => [a] -> [a]
inc xs = foldl go (\_ _ acc -> acc) xs id (+ 1) []
where go run x f g acc = run g f (f x: acc)
Note that even thought this is a left fold, the list is built using cons (:) operator; and it will perform linearly and not quadratic (similar construct as in difference lists).
\> inc [1, 2, 3]
[1,3,3]
\> inc [1, 2, 3, 4]
[2,2,4,4]
It can also be generalized to alternating functions other than id and (+ 1).
I like Thomas's solution. However, I think a simple foldr is enough here.
process = snd . foldr (\x (b,xs) -> (not b, x + fromEnum b:xs)) (False,[])

SML: subtract one list from another list

What is the easiest way to subtract one list from another? Do I need to use ListPair to solve this task? Notic that I need to compare ROWS, not single elements. For instance, there are two lists "L1" and "L2":
L1 =
[(1, 2, 3),
(4, 5, 6)]
L2 =
[(1, 2, 3),
(4, 5, 6),
(3, 2, 3]
I need to get "L3" by applying L3 = L2-L1:
L3 =
[(3, 2, 3)]
Thanks.
As I understand the question, you want to remove the elements in L2 which are also in L1, but only once per occurrence.
A simple solution might involve a helper function to tell you if an element was found in L1, along with the rest of L1 with this element removed.
fun remFirst _ [] rest = (false, rev rest)
| remFirst x (y::ys) rest =
if x = y then
(true, rev rest # ys)
else
remFirst x ys (y :: rest)
Now you can iterate through L2, discarding elements each time remFirst returns true, and then proceeding with the rest of the list.
If instead you want to remove the prefix which L2 has in common with L1, things get a bit simpler.
fun remPref [] _ = []
| remPref xs [] = xs
| remPref (x::xs) (y::ys) = if x = y then remPref xs ys else (x::xs)
UPDATE: The question has now been altered.
If the requirement is now to remove elements from L2 that are in L1, filter is useful.
List.filter (fn x => List.all (fn y => x <> y) L1) L2