Haskell: a case of composition - haskell

This is a useless case of concatenation via foldl, purely educational (for me):
foldl (\xs x -> xs ++ [x]) [1,2] [11,12,13]
[1,2,11,12,13]
Is there a way to pack it even tighter, using composition instead of the lambda?

This is just a better readable summary extracted from the comments by HTNW and Will Ness:
-- Reduction to poinfree
a = \xs x -> xs ++ [x]
b = \xs x -> xs ++ return x
c = \xs x -> ((xs ++) . return) x
d = \xs x -> ((. return) (xs ++)) x
e = \xs x -> ((. return) . (++)) xs x

Related

ConcatMap in haskell without ++

I'm trying to write the code for Haskell concatmap without using the ++ operator where
concatMap :: (a -> [b]) -> [a] -> [b]
and producing the same result of
concatMap f = foldr ((++) . f) []
I'm quite new to Haskell and this was just an exercise I found. Actually, I do not even know if this can be done.
Here's a way that makes the state of the computation explicit:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = go []
where
-- We have b values; use one.
go (b:bs) as = b : go bs as
-- No bs left; get some more.
go [] (a:as) = go (f a) as
-- Nothing left; we're done.
go [] [] = []
This maintains the current list of bs, filling it up whenever it's empty.
This might be cheating, but how about:
myConcatMap f s = concat (map f s)
The concat function uses some sort of ++ in its source code, so that is why you might not like it. You can try to use an alternative concat that does list comprehensions, it has a more "from scratch" feeling.
myconcat ll = [y | x <- ll, y <- x]
You can use the fact that foldr (:) = flip (++)
concatMap f = foldr (flip (foldr (:)) . f) []
Or pointfree:
concatMap = flip foldr [] . (flip (foldr (:)) .)

Define functions with foldl foldr

I understand the definitions of foldl, foldr, but I have problems with functions defined by them.
For example map with foldr:
map f [] = []
map f l = foldr (\x xs -> f x : xs) [] l
I don't understand the (\x xs -> f x : xs). It is the map function, which foldr takes? But shouldn't it be (\x xs -> f x : f xs), because map f (x:xs) = f x : map f xs?
Example with foldl:
concat (x:xs) = x ++ concat xs
concat' xs = foldl (++) [] xs
concat'' xs = foldl (\ys y -> ys ++ y) [] xs
Of course I understand (++), but what's the logic behind (\ys y -> ys ++ y)? Is it ys = [] and y = xs?
So the function takes [] as ys and y is the first element of xs and concates the [] with the y?
Concrete example:
concat'' [1,2,3] = foldl (\ys y -> ys ++ y) [] [1,2,3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [] [1]) [2,3]
=> foldl (\ys y -> ys ++ y) [1] [2,3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [1] [2]) [3]
=> foldl (\ys y -> ys ++ y) [1,2] [3]
=> foldl (\ys y -> ys ++ y) ((\ys y -> ys ++ y) [1,2] [3]) []
=> foldl (\ys y -> ys ++ y) [1,2,3] []
=> [1,2,3]
Another thing: concat only takes 1 list xs, so if I want to concat 2 lists?
concat (x:xs) ys = x ++ concat xs ys
concat [1,2,3] [4,5,6] with foldl?
Reverse:
reverse (x:xs) = reverse xs ++ [x]
reverse' l = foldl (\xs x -> [x] : xs) [] l
reverse'' l = foldr (\x xs -> xs ++ [x]) [] l
The foldr is intuitive clear (with the questions from above), but what's behind the reverse order in foldl (\xs x -> [x] : xs)? This foldl (\x xs -> xs ++ [x]) [] l would be wrong, wouldn't it?
Thanks a lot!
The code
foldr (\x xs -> ...) end list
could be read, roughly, as follows
scan the whole list
if it's empty, just return end end
otherwise:
let x be the element at hand
let xs be the rest of the list, after having been processed
apply the ... operation
The emphasized part is crucial. xs is not the rest of the list, but the result of the "recursive call" on it.
Indeed, xs is a bad name for that. In thee general case, it's not even a list! E.g. one would never write (silly example)
foldr (\x xs -> x + xs) 0 [1..100] -- sum 1..100
but rather prefer something like
foldr (\x partialSum -> x + partialSum) 0 [1..100] -- sum 1..100
(Actually, one would not sum using foldr, but let's leave that aside.)
So, just read it like this:
map f l = foldr (\x mappedTail -> f x : mappedTail) [] l

Associativity of monads

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

returning an element extracted from a monad; redundant?

Are the following two implementations of flatten equivalent for all well-behaved Monads?
flatten1 xss = do
xs <- xss
x <- xs
return x
flatten2 xss = do
xs <- xss
xs
Yes, they're identical. They're desugared as
flatten1 xss =
xss >>= \xs -> xs >>= \x -> return x
flatten2 xss = do
xss >>= \xs -> xs
The first one is equivalent to
xss >>= \xs -> xs >>= return
and by the Right identity monad law equivalent to
xss >>= \xs -> xs
In short, yes. To prove it:
You've written:
xss >>= (\xs -> xs >>= \x -> return x)
xss >>= (\xs -> xs >>= return) -- eta
in the first and
xss >>= (\xs -> xs)
xss >>= id
according to the monad laws, return is a right identity so that
m >>= return === m
so we can do
xss >>= (\ xs -> xs >>= return )
xss >>= (\ xs -> xs )
xss >>= id

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