Associativity of monads - haskell

newtype Set a = Set [a]
New Type Set that contains a list.
empty :: Set a
empty = Set []
sing :: a -> Set a
sing x = Set [x]
Function to creat a set.
memSet :: (Eq a) => a -> Set a -> Bool
memSet _ (Set []) = False
memSet x (Set xs)
| elem x xs = True
| otherwise = False
{-
makeSet :: (Eq a) => [a] -> Set a
makeSet [] = empty
makeset (x:xs) = union (sing x) (makeSet xs)
-- etc
-- we need the obvious stuff:
union :: Set a -> Set a -> Set a
unionMult :: [ Set a ] -> Set a
intersection :: Set a -> Set a -> Set a
subSet :: Set a -> Set a -> Bool
mapSet :: (a -> b) -> Set a -> Set b
mapset f (Set xs) = makeSet (map f xs)
-}
-- now making it a monad:
instance Monad Set where
return = sing
(Set x) >>= f = unionMult (map f x)
Verification:
Left identity:
return a >>= f ≡ f a
Right identity:
m >>= return ≡ m
Associativity:
(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
left:
return x >>= f
(Set [x]) >>= f
unionMult (map f [x])
unionMult [ (f x) ] = f x
right:
(Set [xs]) >>= return
unionMult (map return [xs])
unionMult [ys]
Set [xs]
Need help with the last one.

Since Set a is just a newtype around [a] lets use [] directly. The proofs will be similar so long as we use Set's instances; we'll be able to use []'s constructors (somewhat) directly. That's nice because then we can prove things inductively.
We want to show that for all xs :: [a] xs >>= return == xs. Let's first assume that xs == [].
[] >>= return
unionConcat (map return [])
unionConcat []
[]
Without defining unionConcat we can use this to show that unless unionConcat [] = [] holds, we can't get associativity. We'll keep that in mind for later.
Now we'll do the inductive step, assuming that we have some particular xs :: [a] where xs >>= return == xs, can we show that (x:xs) >>= return == x:xs?
(x:xs) >>= return
unionConcat (map return (x:xs))
unionConcat (return x : map return xs)
...
x : unionConcat (map return xs)
x : (xs >>= return)
x:xs -- working upward from the bottom here
Providing yet another property of unionConcat---
unionConcat (return x : xs) = x : unionConcat xs
So even before we have a definition of unionConcat we can already say that our properties will hold contingent on it following certain properties of its own. We ought to translate the (:) constructor back into a notion for sets, though.
unionConcat (return x : xs) = insert x (unionConcat xs)

unionConcat is already defined in Data.Set.... To be concrete, I will use the following definiitions in this proof
unionConcat = Data.Set.unions
return = Data.Set.fromList [a]
(I will use other functions defined in Data.Set here, some may require "Ord a", presumably that won't be a problem).
I also make use of the following properties
union x y = fromList (toList x ++ toList y)
concat . map (:[]) = id
The first states that the union of two sets can be obtained by taking a list of items in the set, concatinating them, then removing the repeats.... This follows from the definition of what a set is
The second property just states that concat and map (:[]) are inverses of each other. This should also be obvious from the definition of concat
map (:[]) [a, b, c, ....] = [[a], [b], [c], ....]
concat [[a], [b], [c], ....] = [a, b, c, ....]
(In order to really finish this proof, I would have to show that these properties follow from the Haskell definitions of (:[]), concat and union, but this is more detail that I think you want, and the actual definitions might change from version to version, so we will just have to assume that the writers of these functions followed the spirit of how sets and concat should work).
(In case it isn't obvious, remember the monkey operator (:[]) wraps single elements in brackets- (:[]) x = [x]).
Since "unions" is just a multiple appliction of "union", and "concat" is just a multiple application of (++), the first propterty can be generalized to
unions sets = fromList (concat $ map toLists sets)
Now for the proof-
y >>= return
= unions $ map return (toList y)
= unions $ map (fromList . (:[])) (toList y)
= unions $ map fromList $ map (:[]) (toList y)
= unions $ map fromList $ map (:[]) $ toList y
= fromList $ concat $ map toList $ map fromList $ map (:[]) (toList y)
= fromList $ concat $ map (:[]) (toList y)
= fromList $ toList y
= y
QED
Edit- See discussion below, I made a mistake and proved the wrong law (d'oh, I should have just read the title of the question :) ), so I am adding the correct one (associativity) below.
Two prove associativity, we need to use two properties....
property 1 - toList (x >>= f) = su (toList x >>=' toList . f)
property 2 - su (x >>=' f) = su (su x >>=' f)
where su sorts and uniqs a list, ie-
su [4,2,4,1] = [1,2,4],
and >>=' is the array bind operator,
x >>=' f = concat . map f x
The first property should be obvious.... It just states that you can get the result of x >>= f in two different ways, either by applying f to the values in the set x and taking the union, or to the exact same values in the corresponding list, and concating the values. The only hitch is that you might get repeat values in the list (the set couldn't even allow that), so you apply the su function on the right side to canonicalize the result (note that toList also outputs in the same form).
The second property states that if you sort/uniq a result at the end of a pipeline of binds, you can also perform it earlier in the pipeline without changing the answer. Again, this should be obvious.... Adding/removing duplicates or reordering the values with the initial list only add/removes duplicates or reorders the final result. But we are going to remove the duplicates and reorder at the end anyway, so it doesn't matter.
(A more rigorous proof of these two properties could be given based on the definitions of map/concat, toList, etc, but it would blow up the size of this posting.... I'll assume that everyone's intuition is strong enough and continue....)
Using these, I can now show you the proof. The general plan is to use the known associativity of the array bind operator, and the relationship of arrays with sets to show that the set bind operator must also be associative.
Since
toList set1 == toList set2
implies that
set1 == set2
I can prove
toList ((y >>= f) >>= g) = toList (y >>= (\x -> f x >>= g))
to get the desired result.
toList ((y >>= f) >>= g)
su (toList (y >>= f) >>=' toList . g) --by property 1
su (su (toList y >>=' toList . f) >>=' toList . g) --by property 1
su ((toList y >>=' toList . f) >>=' toList . g) --by property 2
su (toList y >>=' (\x -> (toList . f) x >>=' toList . g)) --by the associativity of the array bind operator
su (toList y >>=' (\x -> su (toList (f x) >>=' toList . g))) --by property 2 and associativity of (.)
su (toList y >>=' (\x -> toList (f x >>= g))) --by property 1
su (toList y >>=' toList (\x -> f x >>= g)) --by associativity of (.)
su (su (toList y >>=' toList (\x -> f x >>= g))) --by property 2
su (toList (y >>= (\x -> f x >>= g))) --by property 1
toList (y >>= (\x -> f x >>= g)) --because toList is already sorted/uniqued
QED

> U :: [Setx] --> Set x
>
> (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
> VL(leftSide)
> (m >>= f) >>= g
> (Set x >>= f) >>=g <=>
> (U(map f x)) >>=g <=> (U(map f x)=Set y)
> Set y >>= g <=>
>
>
> HL:(right Side)
> m >>= (\x -> f x >>= g) <=>
> Set x >>=(\x -> f x >>= g) (funktionen \x -> f x gives a Set y it will consume value of x.)
But this prrof i wrong. (U= UnionMult.)
I was told that i should try to create a function conposition for both left side and right side. It will help in showing that right side and left side are equal.
HL: rightSide
VL leftSide
want to show VL==HL

Related

Haskell map until first condition met

I want to map a conditional function only on the first item that passes.
map (>5) [1,2,3,4,5,6,7,8,9]
would result in
[False,False,False,False,False,True,True,True,True]
I'm looking for something that would result in
[False,False,False,False,False,True,False,False,False]
So only the first occurrence of being greater than 5 results in True.
I tried scanl, various folds and tried to roll my own mapUntil kind of thing.
Seems like a simple problem but I'm drawing a blank.
break specifically separates the list in 2 parts where the first part is all False, the opposite of span.
break (>5) [1,2,3,8,2,5,1,7,9]
>>> ([1,2,3],[8,2,5,1,7,9])
Then it's just what chi did:
oneTrue f lst = map (const False) a ++ rest b
where (a,b) = break f lst
rest [] = []
rest (x:xs) = True : map (const False) xs
A basic solution:
mapUntil p = onlyOne . map p
where
onlyOne [] = []
onlyOne (x:xs)
| x = True : map (const False) xs
| otherwise = False : onlyOne xs
With library helpers:
mapUntil p = snd . mapAccumL (\x y -> (x||y, not x && y)) False . map p
Above x is a boolean standing for "have seen a true before?", as a kind-of state. y is the list element. x||y is the new state, while not x && y is the new list element.
Alternatively (using Control.Arrow.second):
mapUntil p = uncurry (++) . second go . break id . map p
where
go [] = []
go (x:xs) = x : map (const False) xs
I would use the mapAccumL tool like;
λ> Data.List.mapAccumL (\b n -> if b then (b, (not b)) else (n > 5, n > 5)) False [1,2,3,4,5,6,7,8,9]
(True,[False,False,False,False,False,True,False,False,False])
Here we carry the b as the state of our interim calculations and in every step decide according to it's previous state. Obviously you need the snd part of the final result.
Edit : After reading the new comment of #Gord under his question I decided to extend my answer to cover his true problem.
Rephrasing the case event of branch that starts with pointerPress (x,y) into...
To start with, you never use x or y from the pattern match (x,y) so lets call it c. Then...
PointerPress c -> State circleCoords circleColors circleDraggeds c
where
bools = fmap checkMouseOverlaps $ (,) <$> circleCoords <*> [c]
circleDraggeds = snd $ mapAccumL (\a b -> if a then (a, not a)
else (b,b)) False bools
What's happening part;
(,) <$> circleCoords <*> [c]
circleCoords is a list of coordinates like [c0,c1,c2] and we fmap (the infix version (<$>) here) (,) function to it and it becomes an applicative of coordinates like [(c0,),(c1,),(c2,)]. Then we apply it to [c] aka [(x,y)] to turn it into [(c0,c),(c1,c),(c2,c)].
fmap checkMouseOverlaps $ toAbove
obviously yields to
[checkMouseOverlaps (c0,c), checkMouseOverlaps (c1,c), checkMouseOverlaps (c2,c)]
which is bools :: [Bool].
The the rest follows the logic explained at the top of my answer.
circleDraggeds = snd $ mapAccumL (\a b -> if a then (a, not a)
else (b,b)) False bools
This can be solve directly with recursion. Similar to chi's solution but without function composition
mapUntil :: (a -> Bool) -> [a] -> [Bool]
mapUntil _ [] = []
mapUntil f (x:xs) =
let b = f x -- calculate f x
in if b -- if true
then b : map (const False) xs -- prepend to the solution and map False to the rest of the list (b is True)
else b : mapUntil f xs -- keep applying mapUntil (b is False)
>>> mapUntil (>5) [1,2,3,4,5,6,7,8,9]
[False,False,False,False,False,True,False,False,False]
Map the condition over the list, then zip the result with the False prefix of the result concatenated with a True followed by an infinite list of Falses:
{-# LANGUAGE BlockArguments, ApplicativeDo, ViewPatterns #-}
import Control.Applicative (ZipList(..))
f :: (a -> Bool) -> [a] -> [Bool]
f cond (map cond -> bs) = getZipList do
r <- ZipList $ takeWhile not bs ++ [True] ++ repeat False
_ <- ZipList $ bs
pure r
or, equivalently:
f' :: (a -> Bool) -> [a] -> [Bool]
f' cond (map cond -> bs) = zipWith const (takeWhile not bs ++ [True] ++ repeat False) bs

Define bind without join for the list monad in Haskell

I understand the definition of >>= in term of join
xs >>= f = join (fmap f xs)
which also tells us that fmap + join yields >>=
I was wondering if for the List monad it's possible to define without join, as we do for example for Maybe:
>>= m f = case m of
Nothing -> Nothing
Just x -> f x
Sure. The actual definition in GHC/Base.hs is in terms of the equivalent list comprehension:
instance Monad [] where
xs >>= f = [y | x <- xs, y <- f x]
Alternatively, you could try the following method of working it out from scratch from the type:
(>>=) :: [a] -> (a -> [b]) -> [b]
We need to handle two cases:
[] >>= f = ???
(x:xs) >>= f = ???
The first is easy. We have no elements of type a, so we can't apply f. The only thing we can do is return an empty list:
[] >>= f = []
For the second, x is a value of type a, so we can apply f giving us a value of f x of type [b]. That's the beginning of our list, and we can concatenate it with the rest of the list generated by a recursive call:
(x:xs) >>= f = f x ++ (xs >>= f)

If I can define a function in terms of foldl, would it make it tail recursive?

I was given an assignment in my functional programming course that asks me to rewrite several functions, like map and filter to be tail recursive.
I'm not 100% sure how to go about this yet but I know that you can define functions by calling foldr and foldl. I know foldl is tail recursive, so if I can define say, filter with foldl, would it become tail recursive, too?
There are two ways to make a recursive function tail recursive:
Convert the function to accumulator passing style. This only works in some cases.
Convert the function to continuation passing style. This works in all cases.
Consider the definition of the map function:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
In accumulator passing style, we have an additional argument which accumulates the result:
mapA :: (a -> b) -> [a] -> [b] -> [b]
mapA _ [] = id
mapA f (x:xs) = mapA f xs . (f x :)
The original map function can be recovered as follows:
map :: (a -> b) -> [a] -> [b]
map f xs = reverse $ mapA f xs []
Note that we need to reverse the result. This is because mapA accumulates the result in reverse:
> mapA (+1) [1,2,3,4,5] []
> mapA (+1) [2,3,4,5] [2]
> mapA (+1) [3,4,5] [3,2]
> mapA (+1) [3,5] [4,3,2]
> mapA (+1) [5] [5,4,3,2]
> mapA (+1) [] [6,5,4,3,2]
> [6,5,4,3,2]
Now, consider continuation passing style:
mapK :: (a -> b) -> [a] -> ([b] -> r) -> r
mapK _ [] k = k []
mapK f (x:xs) k = mapK f xs (k . (f x :))
The original map function can be recovered as follows:
map :: (a -> b) -> [a] -> [b]
map f xs = mapK f xs id
Note that we do not need to reverse the result. This is because although mapK accumulates the continuations in reverse, yet when finally applied to the base case the continuations are unfolded to produce the result in the correct order:
> mapK (+1) [1,2,3,4,5] id
> mapK (+1) [2,3,4,5] (id . (2:))
> mapK (+1) [3,4,5] (id . (2:) . (3:))
> mapK (+1) [4,5] (id . (2:) . (3:) . (4:))
> mapK (+1) [5] (id . (2:) . (3:) . (4:) . (5:))
> mapK (+1) [] (id . (2:) . (3:) . (4:) . (5:) . (6:))
> (id . (2:) . (3:) . (4:) . (5:) . (6:)) []
> (id . (2:) . (3:) . (4:) . (5:)) [6]
> (id . (2:) . (3:) . (4:)) [5,6]
> (id . (2:) . (3:)) [4,5,6]
> (id . (2:)) [3,4,5,6]
> id [2,3,4,5,6]
> [2,3,4,5,6]
Note, that in both cases we're doing twice the required amount of work:
First, we accumulate an intermediate result in reverse order.
Next, we produce the final result in the correct order.
Some functions can be written efficiently in the accumulator passing style (e.g. the sum function):
sumA :: Num a => [a] -> a -> a
sumA [] = id
sumA (x:xs) = sumA xs . (+ x)
The original sum function can be recovered as follows:
sum :: Num a => [a] -> a
sum xs = sumA xs 0
Note that we don't need to do any post processing on the result.
However, list functions written in tail recursive style always need to be reversed. Hence, we do not write list functions in tail recursive style. Instead, we depend upon laziness to process only as much of the list as required.
It should be noted that continuation passing style is just a special case of accumulator passing style. Since foldl is both tail recursive and uses an accumulator, you can write mapA and mapK using foldl as follows:
mapA :: (a -> b) -> [a] -> [b] -> [b]
mapA f xs acc = foldl (\xs x -> f x : xs) acc xs
mapK :: ([b] -> r) -> (a -> b) -> [a] -> r
mapK k f xs = foldl (\k x xs -> k (f x : xs)) k xs []
For, mapK if you take the k to be id then you get map:
map :: (a -> b) -> [a] -> [b]
map f xs = foldl (\k x xs -> k (f x : xs)) id xs []
Similarly, for filter:
filter :: (a -> Bool) -> [a] -> [a]
filter p xs = foldl (\k x xs -> k (if p x then x : xs else xs)) id xs []
There you have it, tail recursive map and filter functions. However, don't forget that they are actually doing twice the work. In addition, they won't work for infinite lists because the result will not be generated until the end of the list is reached (which will never happen for infinite lists).
I'm suspecting the professor/lecturer is expecting solutions where tail recursion is used "directly", i.e. lexically, within the source code of the function, not indirectly, or "dynamically", where tail recursion only happens at runtime within the scope of some subroutine call.
Otherwise, you might as well supply e.g. Prelude.foldl as the implementation for a custom foldl of yours, since it, possibly, uses tail recursion under the hood, and thus does yours:
import Prelude as P
foldl = P.foldl
but obviously something like that wouldn't be accepted.

Haskell: List Comprehensions and higher-order functions

I've tried to transform the following list comprehension:
f xs = [ x+8 | (x,_) <- xs ]
using higher-order functions.
My first solution was:
f' xs = map (\(x,_) -> x+8) xs
After I tried various other approaches, I found out that the following also works:
f' xs = map((+8).fst) xs
Both versions of f' give the same (correct) output, but I don't understand why (+8).fst is equal to \(x,_) -> x+8 when using map on a list of tuples.
The definition of fst is
fst :: (a, b) -> a
fst (a, _) = a
and the definition of (.) is
(.) :: (b -> c) -> (a -> b) -> a -> c
(f . g) = \x -> f (g x)
If we use these definitions to expand your function, we get
f' xs = map ((+8) . fst) xs
f' xs = map (\x -> (+8) (fst x)) xs -- definition of (.)
f' xs = map (\x -> (+8) ((\(a, _) -> a) x)) -- definition of fst
f' xs = map (\(a, _) -> (+8) a) -- we can move the pattern matching
f' xs = map (\(a, _) -> a + 8) -- expand section
Both versions of f' give the same (correct) output, but I don't understand why (+8).fst is equal to (x,_) -> x+8 when using map on a list of tuples.
The type of fst is:
fst :: (a, b) -> a
and what it does is it takes the first element of a pair (a tuple of two elements).
The type of (+8) is:
(+8) :: Num a => a -> a
and what it does is it takes as input a Num, applies + 8 to it and returns the result.
Now, the type of (+8) . fst is:
((+8).fst) :: Num c => (c, b) -> c
which is the composition of fst and (+8). Specifically it's the function that takes as input a pair, extracts the first element and adds 8 to it.
This can be easily seen by seen an example:
((+8).fst) (3, 'a')
-- 11
The same thing happens with \ (x, _) -> x + 8. You take a pair as input (in the lambda), pattern match the first argument to x, increment it by 8 and return it:
(\ (x, _) -> x + 8) (3, 'a')
-- 11

Recursively sort non-contiguous list to list of contiguous lists

I've been trying to learn a bit of functional programming (with Haskell & Erlang) lately and I'm always amazed at the succinct solutions people can come up with when they can think recursively and know the tools.
I want a function to convert a list of sorted, unique, non-contiguous integers into a list of contiguous lists, i.e:
[1,2,3,6,7,8,10,11]
to:
[[1,2,3], [6,7,8], [10,11]
This was the best I could come up with in Haskell (two functions)::
make_ranges :: [[Int]] -> [Int] -> [[Int]]
make_ranges ranges [] = ranges
make_ranges [] (x:xs)
| null xs = [[x]]
| otherwise = make_ranges [[x]] xs
make_ranges ranges (x:xs)
| (last (last ranges)) + 1 == x =
make_ranges ((init ranges) ++ [(last ranges ++ [x])]) xs
| otherwise = make_ranges (ranges ++ [[x]]) xs
rangify :: [Int] -> [[Int]]
rangify lst = make_ranges [] lst
It might be a bit subjective but I'd be interested to see a better, more elegant, solution to this in either Erlang or Haskell (other functional languages too but I might not understand it.) Otherwise, points for just fixing my crappy beginner's Haskell style!
Most straightforward way in my mind is a foldr:
ranges = foldr step []
where step x [] = [[x]]
step x acc#((y:ys):zs) | y == x + 1 = (x:y:ys):zs
| otherwise = [x]:acc
Or, more concisely:
ranges = foldr step []
where step x ((y:ys):zs) | y == x + 1 = (x:y:ys):zs
step x acc = [x]:acc
But wait, there's more!
abstractRanges f = foldr step []
where step x ((y:ys):zs) | f x y = (x:y:ys):zs
step x acc = [x]:acc
ranges = abstractRanges (\x y -> y == x + 1)
powerRanges = abstractRanges (\x y -> y == x*x) -- mighty morphin
By turning the guard function into a parameter, you can group more interesting things than just +1 sequences.
*Main> powerRanges [1,1,1,2,4,16,3,9,81,5,25]
[[1,1,1],[2,4,16],[3,9,81],[5,25]]
The utility of this particular function is questionable...but fun!
I can't believe I got the shortest solution. I know this is no code golf, but I think it is still quite readable:
import GHC.Exts
range xs = map (map fst) $ groupWith snd $ zipWith (\a b -> (a, a-b)) xs [0..]
or pointfree
range = map (map snd) . groupWith fst . zipWith (\a b -> (b-a, b)) [0..]
BTW, groupWith snd can be replaced with groupBy (\a b -> snd a == snd b) if you prefer Data.List over GHC.Exts
[Edit]
BTW: Is there a nicer way to get rid of the lambda (\a b -> (b-a, b)) than (curry $ (,) <$> ((-) <$> snd <*> fst) <*> snd) ?
[Edit 2]
Yeah, I forgot (,) is a functor. So here is the obfuscated version:
range = map (map fst) . groupWith snd . (flip $ zipWith $ curry $ fmap <$> (-).fst <*> id) [0..]
Suggestions are welcome...
import Data.List (groupBy)
ranges xs = (map.map) snd
. groupBy (const fst)
. zip (True : zipWith ((==) . succ) xs (tail xs))
$ xs
As to how to come up with such a thing: I started with the zipWith f xs (tail xs), which is a common idiom when you want to do something on consecutive elements of a list. Likewise is zipping up a list with information about the list, and then acting (groupBy) upon it. The rest is plumbing.
Then, of course, you can feed it through #pl and get:
import Data.List (groupBy)
import Control.Monad (ap)
import Control.Monad.Instances()
ranges = (((map.map) snd)
. groupBy (const fst))
.) =<< zip
. (True:)
. ((zipWith ((==) . succ)) `ap` tail)
, which, by my authoritative definition, is evil due to Mondad ((->) a). Twice, even. The data flow is meandering too much to lay it out in any sensible way. zipaptail is an Aztec god, and Aztec gods aren't to be messed with.
Another version in Erlang:
part(List) -> part(List,[]).
part([H1,H2|T],Acc) when H1 =:= H2 - 1 ->
part([H2|T],[H1|Acc]);
part([H1|T],Acc) ->
[lists:reverse([H1|Acc]) | part(T,[])];
part([],Acc) -> Acc.
k z = map (fst <$>) . groupBy (const snd) .
zip z . (False:) . (zipWith ((==) . succ) <*> tail) $ z
Try reusing standard functions.
import Data.List (groupBy)
rangeify :: (Num a) => [a] -> [[a]]
rangeify l = map (map fst) $ groupBy (const snd) $ zip l contigPoints
where contigPoints = False : zipWith (==) (map (+1) l) (drop 1 l)
Or, following (mixed) advice to use unfoldr, stop abusing groupBy, and be happy using partial functions when it doesn't matter:
import Control.Arrow ((***))
import Data.List (unfoldr)
spanContig :: (Num a) => [a] -> [[a]]
spanContig l =
map fst *** map fst $ span (\(a, b) -> a == b + 1) $ zip l (head l - 1 : l)
rangeify :: (Num a) => [a] -> [[a]]
rangeify = unfoldr $ \l -> if null l then Nothing else Just $ spanContig l
Erlang using foldr:
ranges(List) ->
lists:foldr(fun (X, [[Y | Ys], Acc]) when Y == X + 1 ->
[[X, Y | Ys], Acc];
(X, Acc) ->
[[X] | Acc]
end, [], List).
This is my v0.1 and I can probably make it better:
makeCont :: [Int] -> [[Int]]
makeCont [] = []
makeCont [a] = [[a]]
makeCont (a:b:xs) = if b - a == 1
then (a : head next) : tail next
else [a] : next
where
next :: [[Int]]
next = makeCont (b:xs)
And I will try and make it better. Edits coming I think.
As a comparison, here's an implementation in Erlang:
partition(L) -> [lists:reverse(T) || T <- lists:reverse(partition(L, {[], []}))].
partition([E|L], {R, [EL|_] = T}) when E == EL + 1 -> partition(L, {R, [E|T]});
partition([E|L], {R, []}) -> partition(L, {R, [E]});
partition([E|L], {R, T}) -> partition(L, {[T|R], [E]});
partition([], {R, []}) -> R;
partition([], {R, T}) -> [T|R].
The standard paramorphism recursion scheme isn't in Haskell's Data.List module, though I think it should be. Here's a solution using a paramorphism, because you are building a list-of-lists from a list, the cons-ing is a little tricksy:
contig :: (Eq a, Num a) => [a] -> [[a]]
contig = para phi [] where
phi x ((y:_),(a:acc)) | x + 1 == y = (x:a):acc
phi x (_, acc) = [x]:acc
Paramorphism is general recursion or a fold with lookahead:
para :: (a -> ([a], b) -> b) -> b -> [a] -> b
para phi b [] = b
para phi b (x:xs) = phi x (xs, para phi b xs)
It can be pretty clear and simple in the Erlang:
partition([]) -> [];
partition([A|T]) -> partition(T, [A]).
partition([A|T], [B|_]=R) when A =:= B+1 -> partition(T, [A|R]);
partition(L, P) -> [lists:reverse(P)|partition(L)].
Edit: Just for curiosity I have compared mine and Lukas's version and mine seems about 10% faster either in native either in bytecode version on testing set what I generated by lists:usort([random:uniform(1000000)||_<-lists:seq(1,1000000)]) on R14B01 64b version at mine notebook. (Testing set is 669462 long and has been partitioned to 232451 sublists.)
Edit2: Another test data lists:usort([random:uniform(1000000)||_<-lists:seq(1,10000000)]), length 999963 and 38 partitions makes bigger diference in native code. Mine version finish in less than half of time. Bytecode version is only about 20% faster.
Edit3: Some microoptimizations which provides additional performance but leads to more ugly and less maintainable code:
part4([]) -> [];
part4([A|T]) -> part4(T, A, []).
part4([A|T], B, R) when A =:= B+1 -> part4(T, A, [B|R]);
part4([A|T], B, []) -> [[B]|part4(T, A, [])];
part4([A|T], B, R) -> [lists:reverse(R, [B])|part4(T, A, [])];
part4([], B, R) -> [lists:reverse(R,[B])].
Here's an attempt from a haskell noob
ranges ls = let (a, r) = foldl (\(r, a#(h:t)) e -> if h + 1 == e then (r, e:a) else (a:r, [e])) ([], [head ls]) (tail ls)
in reverse . map reverse $ r : a

Resources