Haskell, list of lists from a tree - list

I have this data structure for a tree:
data Tree a = NodeT a (Tree a) ( Tree a) | EmptyT
I need to create a function that returns a list of lists where each element of the list represents a level of the tree. For instance, from this:
1
/ \
2 3
/ \ / \
4 5 6 7
to this: [[1],[2,3],[4,5,6,7]]
The function must have the following form:
f :: Tree a -> [[a]]
How to do it using recursion?
anyone?
Thanks

Answer
levels :: Tree a -> [[a]]
levels t = levels' t []
levels' :: Tree a -> [[a]] -> [[a]]
levels' EmptyT rest = rest
levels' (NodeT a l r) [] = [a] : levels' l (levels r)
levels' (NodeT a l r) (x : xs) = (a : x) : levels' l (levels' r xs)
A slightly more complicated, but lazier, implementation of levels':
levels' EmptyT rest = rest
levels' (NodeT a l r) rest = (a : front) : levels' l (levels' r back)
where
(front, back) = case rest of
[] -> ([], [])
(x : xs) -> (x, xs)
Fans of folds will note that these are structured as catamorphisms:
cata :: (a -> b -> b -> b) -> b -> Tree a -> b
cata n e = go
where
go EmptyT = e
go (NodeT a l r) = n a (go l) (go r)
levels t = cata br id t []
where
br a l r rest = (a : front) : l (r back)
where
(front, back) = case rest of
[] -> ([], [])
(x : xs) -> (x, xs)
As chi points out, there seems to be some connection between this general approach and the result of using Jakub Daniel's solution with difference lists as intermediate forms. This could look something like
import Data.Monoid
levels :: Tree a -> [[a]]
levels = map (flip appEndo []) . (cata br [])
where
br :: a -> [Endo [a]] -> [Endo [a]] -> [Endo [a]]
br a l r = Endo (a :) : merge l r
merge :: Monoid a => [a] -> [a] -> [a]
merge [] ys = ys
merge (x : xs) ys = (x <> y) : merge xs ys'
where
(y,ys') =
case ys of
[] -> (mempty, [])
p : ps -> (p, ps)
I'm not entirely sure just how this compares with the more direct approaches.
Discussion
Kostiantyn Rybnikov's answer cites Okasaki's Breadth-First Numbering: Lessons from a Small Exercise in Algorithm Design, an excellent paper that highlights many functional programmers' "blind spots" and offers good arguments for making abstract data types easy enough to use that they won't be missed. However, the problem that paper describes is significantly more complex than this one; not so much machinery is required here. Also, the paper notes that level-oriented solutions are actually slightly faster than queue-based ones in ML; I'd expect to see a larger difference in a lazy language like Haskell.
Jakub Daniel's answer attempts a level-oriented solution, but unfortunately has an efficiency problem. It builds each level by repeatedly appending one list to another, and those lists may all be of equal length. Thus in the worst case, if I am calculating this correctly, it takes O(n log n) to process a tree with n elements.
The approach I chose is level-oriented, but avoids the pain of concatenation by passing each left subtree the levels of its right sibling and cousins. Each node/leaf of the tree is processed exactly once. That processing involves O(1) work: pattern matching on that node/leaf, and, if it is a node, pattern matching on the list derived from the right sibling and cousins. Thus the total time is O(n) to process a tree with n elements.

You recursively compute the levels and always merge lists from two subtrees point-wise (thus all the slices in the same depth get merged together).
f :: Tree a -> [[a]]
f EmptyT = []
f (NodeT a t1 t2) = [a] : merge (f t1) (f t2)
merge :: [[a]] -> [[a]] -> [[a]]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = (x ++ y) : merge xs ys
If the tree were complete (all the paths from the root to a list are of the same length) then you could use zipWith (++) as merge.

Slightly more complicated solution, than the one which was accepted, but I think mine might be better in terms of memory consumption (it's a bit late, so please check yourself).
Intuition goes from a wonderful paper of Chris Okasaki "Breadth-First Numbering: Lessons from a Small Exercise in Algorithm Design". You can get general intuition on breadth-first tree traversals of trees in functional languages in detail.
I did somewhat ugly addition to add the "list of lists" splitting, there might be a better way:
module Main where
data Tree a = NodeT a (Tree a) (Tree a) | EmptyT
-- 1
-- / \
-- 2 3
-- / \ / \
-- 4 5 6 7
f :: Tree a -> [[a]]
f t = joinBack (f' [(t, True)])
type UpLevel = Bool
f' :: [(Tree a, UpLevel)] -> [(a, UpLevel)]
f' [] = []
f' ((EmptyT, _) : ts) = f' ts
f' ((NodeT a t1 t2, up) : ts) = (a, up) : f' (ts ++ [(t1, up)] ++ [(t2, False)])
joinBack :: [(a, UpLevel)] -> [[a]]
joinBack = go []
where
go acc [] = [reverse acc]
go acc ((x, False) : xs) = go (x : acc) xs
go acc ((x, True) : xs) = reverse acc : go [] ((x, False):xs)
main :: IO ()
main = do
let tree = NodeT 1 (NodeT 2 (NodeT 4 EmptyT EmptyT) (NodeT 5 EmptyT EmptyT))
(NodeT 3 (NodeT 6 EmptyT EmptyT) (NodeT 7 EmptyT EmptyT))
:: Tree Int
print (tail (f tree))

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.

How do you convert a list of numbers into a list of ranges in haskell?

Say you have a list of numbers, [1,2,3,5,6,7,8,9,11,12,15,16,17]
and you want a function that takes that as an input and returns something like
[[1,3],[5,9],[11,12],[15,17]] or alternatively maybe
[(1,3), (5,9), (11,12), (15,17)]
how would this be done? all of the solutions i've found online are very very long and quite convoluted, when this seems like such an easy problem for a functional language like haskell
So we have a list of numbers,
xs = [1,2,3,5,6,7,8,9,11,12,14,16,17] -- 14 sic!
We turn it into a list of segments,
ys = [[x,x+1] | x <- xs]
-- [[1,2], [2,3], [3,4], [5,6], ..., [11,12], [12,13], [14,15], [16,17], [17,18] ]
we join the touching segments,
zs = foldr g [] ys
-- [[1,4], [5,10], [11,13], [14,15], [16,18]]
where
g [a,b] [] = [[a,b]]
g [a,b] r#([c,d]:t) | b==c = [a,d]:t
| otherwise = [a,b]:r
and we subtract 1 from each segment's ending value,
ws = [[a,b-1] | [a,b] <- zs]
-- [[1,3], [5,9], [11,12], [14,14], [16,17]]
All in all we get
ranges :: (Num t, Eq t) => [t] -> [[t]]
ranges = map (\[a,b] -> [a,b-1]) . foldr g [] . map (\x -> [x,x+1])
where
g [a,b] [] = [[a,b]]
g [a,b] r#([c,d]:t) | b==c = [a,d]:t
| otherwise = [a,b]:r
Simple and clear.
edit: or, to be properly lazy,
where
g [a,b] r = [a,x]:y
where
(x,y) = case r of ([c,d]:t) | b==c -> (d,t) -- delay forcing
_ -> (b,r)
update: as dfeuer notes, (a,a) type is better than [a,a]. Wherever [P,Q] appears in this code, replace it with (P,Q). This will improve the code, with zero cost to readability.
I would definitely prefer the alternative representation to the first one you give.
ranges :: (Num a, Eq a) => [a] -> [(a,a)]
ranges [] = []
ranges (a : as) = ranges1 a as
-- | A version of 'ranges' for non-empty lists, where
-- the first element is supplied separately.
ranges1 :: (Num a, Eq a) => a -> [a] -> [(a,a)]
ranges1 a as = (a, b) : bs
where
-- Calculate the right endpoint and the rest of the
-- result lazily, when needed.
(b, bs) = finish a as
-- | This takes the left end of the current interval
-- and the rest of the list and produces the right endpoint of
-- that interval and the rest of the result.
finish :: (Num a, Eq a) => a -> [a] -> (a, [(a, a)])
finish l [] = (l, [])
finish l (x : xs)
| x == l + 1 = finish x xs
| otherwise = (l, ranges1 x xs)
To solve the Rosetta Code problem linked in the comment above, this isn't really quite an optimal representation. I'll try to explain how to match the representation more precisely later.
So one might do it like the idea from #Will Ness on the stateful folding or mine under the same answer. All explanations are to be found there. Besides, if you get curious and want to read more about it then have a look at Haskell Continuation Passing Style page. I am currently trying to gerealize this in such a way that we can have a variant of foldr1 in a stateful manner. A foldS :: Foldable t => (a -> a -> b) -> t a -> b. However this is still not general stateful folding. It's just tailored to this question.
ranges :: (Ord a, Num a) => [a] -> [[a]]
ranges xs = foldr go return xs $ []
where
go :: (Ord a, Num a) => a -> ([a] -> [[a]]) -> ([a] -> [[a]])
go c f = \ps -> let rrs#(r:rs) = f [c]
in case ps of
[] -> [c]:r:rs
[p] -> if p + 1 == c then rrs else [p]:(c:r):rs
*Main> ranges [1,2,3,5,6,7,8,9,11,12,15,16,17]
[[1,3],[5,9],[11,12],[15,17]]
I haven't had time to test any edge cases. All advices are welcome.

haskell: how to get list of numbers which are higher then their neighbours in a starting list

I am trying to learn Haskell and I want to solve one task. I have a list of Integers and I need to add them to another list if they are bigger then both of their neighbors. For Example:
I have a starting list of [0,1,5,2,3,7,8,4] and I need to print out a list which is [5, 8]
This is the code I came up but it returns an empty list:
largest :: [Integer]->[Integer]
largest n
| head n > head (tail n) = head n : largest (tail n)
| otherwise = largest (tail n)
I would solve this as outlined by Thomas M. DuBuisson. Since we want the ends of the list to "count", we'll add negative infinities to each end before creating triples. The monoid-extras package provides a suitable type for this.
import Data.Monoid.Inf
pad :: [a] -> [NegInf a]
pad xs = [negInfty] ++ map negFinite xs ++ [negInfty]
triples :: [a] -> [(a, a, a)]
triples (x:rest#(y:z:_)) = (x,y,z) : triples rest
triples _ = []
isBig :: Ord a => (a,a,a) -> Bool
isBig (x,y,z) = y > x && y > z
scnd :: (a, b, c) -> b
scnd (a, b, c) = b
finites :: [Inf p a] -> [a]
finites xs = [x | Finite x <- xs]
largest :: Ord a => [a] -> [a]
largest = id
. finites
. map scnd
. filter isBig
. triples
. pad
It seems to be working appropriately; in ghci:
> largest [0,1,5,2,3,7,8,4]
[5,8]
> largest [10,1,10]
[10,10]
> largest [3]
[3]
> largest []
[]
You might also consider merging finites, map scnd, and filter isBig in a single list comprehension (then eliminating the definitions of finites, scnd, and isBig):
largest :: Ord a => [a] -> [a]
largest xs = [x | (a, b#(Finite x), c) <- triples (pad xs), a < b, c < b]
But I like the decomposed version better; the finites, scnd, and isBig functions may turn out to be useful elsewhere in your development, especially if you plan to build a few variants of this for different needs.
One thing you might try is lookahead. (Thomas M. DuBuisson suggested a different one that will also work if you handle the final one or two elements correctly.) Since it sounds like this is a problem you want to solve on your own as a learning exercise, I’ll write a skeleton that you can take as a starting-point if you want:
largest :: [Integer] -> [Integer]
largest [] = _
largest [x] = _ -- What should this return?
largest [x1,x2] | x1 > x2 = _
| x1 < x2 = _
| otherwise = _
largest [x1,x2,x3] | x2 > x1 && x2 > x3 = _
| x3 > x2 = _
| otherwise = _
largest (x1:x2:x3:xs) | x2 > x1 && x2 > x3 = _
| otherwise = _
We need the special case of [x1,x2,x3] in addition to (x1:x2:x3:[]) because, according to the clarification in your comment, largest [3,3,2] should return []. but largest [3,2] should return [3]. Therefore, the final three elements require special handling and cannot simply recurse on the final two.
If you also want the result to include the head of the list if it is greater than the second element, you’d make this a helper function and your largest would be something like largest (x1:x2:xs) = (if x1>x2 then [x1] else []) ++ largest' (x1:x2:xs). That is, you want some special handling for the first elements of the original list, which you don’t want to apply to all the sublists when you recurse.
As suggested in the comments, one approach would be to first group the list into tuples of length 3 using Preludes zip3 and tail:
*Main> let xs = [0,1,5,2,3,7,8,4]
*Main> zip3 xs (tail xs) (tail (tail xs))
[(0,1,5),(1,5,2),(5,2,3),(2,3,7),(3,7,8),(7,8,4)]
Which is of type: [a] -> [b] -> [c] -> [(a, b, c)] and [a] -> [a] respectively.
Next you need to find a way to filter out the tuples where the middle element is bigger than the first and last element. One way would be to use Preludes filter function:
*Main> let xs = [(0,1,5),(1,5,2),(5,2,3),(2,3,7),(3,7,8),(7,8,4)]
*Main> filter (\(a, b, c) -> b > a && b > c) xs
[(1,5,2),(7,8,4)]
Which is of type: (a -> Bool) -> [a] -> [a]. This filters out elements of a list based on a Boolean returned from the predicate passed.
Now for the final part, you need to extract the middle element from the filtered tuples above. You can do this easily with Preludes map function:
*Main> let xs = [(1,5,2),(7,8,4)]
*Main> map (\(_, x, _) -> x) xs
[5,8]
Which is of type: (a -> b) -> [a] -> [b]. This function maps elements from a list of type a to b.
The above code stitched together would look like this:
largest :: (Ord a) => [a] -> [a]
largest xs = map (\(_, x, _) -> x) $ filter (\(a, b, c) -> b > a && b > c) $ zip3 xs (tail xs) (tail (tail xs))
Note here I used typeclass Ord, since the above code needs to compare with > and <. It's fine to keep it as Integer here though.

Zip with default value instead of dropping values?

I'm looking for a function in haskell to zip two lists that may vary in length.
All zip functions I could find just drop all values of a lists that is longer than the other.
For example:
In my exercise I have two example lists.
If the first one is shorter than the second one I have to fill up using 0's. Otherwise I have to use 1's.
I'm not allowed to use any recursion. I just have to use higher order functions.
Is there any function I can use?
I really could not find any solution so far.
There is some structure to this problem, and here it comes. I'll be using this stuff:
import Control.Applicative
import Data.Traversable
import Data.List
First up, lists-with-padding are a useful concept, so let's have a type for them.
data Padme m = (:-) {padded :: [m], padder :: m} deriving (Show, Eq)
Next, I remember that the truncating-zip operation gives rise to an Applicative instance, in the library as newtype ZipList (a popular example of a non-Monad). The Applicative ZipList amounts to a decoration of the monoid given by infinity and minimum. Padme has a similar structure, except that its underlying monoid is positive numbers (with infinity), using one and maximum.
instance Applicative Padme where
pure = ([] :-)
(fs :- f) <*> (ss :- s) = zapp fs ss :- f s where
zapp [] ss = map f ss
zapp fs [] = map ($ s) fs
zapp (f : fs) (s : ss) = f s : zapp fs ss
I am obliged to utter the usual incantation to generate a default Functor instance.
instance Functor Padme where fmap = (<*>) . pure
Thus equipped, we can pad away! For example, the function which takes a ragged list of strings and pads them with spaces becomes a one liner.
deggar :: [String] -> [String]
deggar = transpose . padded . traverse (:- ' ')
See?
*Padme> deggar ["om", "mane", "padme", "hum"]
["om ","mane ","padme","hum "]
This can be expressed using These ("represents values with two non-exclusive possibilities") and Align ("functors supporting a zip operation that takes the union of non-uniform shapes") from the these library:
import Data.Align
import Data.These
zipWithDefault :: Align f => a -> b -> f a -> f b -> f (a, b)
zipWithDefault da db = alignWith (fromThese da db)
salign and the other specialised aligns in Data.Align are also worth having a look at.
Thanks to u/WarDaft, u/gallais and u/sjakobi over at r/haskell for pointing out this answer should exist here.
You can append an inifinte list of 0 or 1 to each list and then take the number you need from the result zipped list:
zipWithDefault :: a -> b -> [a] -> [b] -> [(a,b)]
zipWithDefault da db la lb = let len = max (length la) (length lb)
la' = la ++ (repeat da)
lb' = lb ++ (repeat db)
in take len $ zip la' lb'
This should do the trick:
import Data.Maybe (fromMaybe)
myZip dx dy xl yl =
map (\(x,y) -> (fromMaybe dx x, fromMaybe dy y)) $
takeWhile (/= (Nothing, Nothing)) $
zip ((map Just xl) ++ (repeat Nothing)) ((map Just yl) ++ (repeat Nothing))
main = print $ myZip 0 1 [1..10] [42,43,44]
Basically, append an infinite list of Nothing to the end of both lists, then zip them, and drop the results when both are Nothing. Then replace the Nothings with the appropriate default value, dropping the no longer needed Justs while you're at it.
No length, no counting, no hand-crafted recursions, no cooperating folds. transpose does the trick:
zipLongest :: a -> b -> [a] -> [b] -> [(a,b)]
zipLongest x y xs ys = map head . transpose $ -- longest length;
[ -- view from above:
zip xs
(ys ++ repeat y) -- with length of xs
, zip (xs ++ repeat x)
ys -- with length of ys
]
The result of transpose is as long a list as the longest one in its input list of lists. map head takes the first element in each "column", which is the pair we need, whichever the longest list was.
(update:) For an arbitrary number of lists, efficient padding to the maximal length -- aiming to avoid the potentially quadratic behaviour of other sequentially-combining approaches -- can follow the same idea:
padAll :: a -> [[a]] -> [[a]]
padAll x xss = transpose $
zipWith const
(transpose [xs ++ repeat x | xs <- xss]) -- pad all, and cut
(takeWhile id . map or . transpose $ -- to the longest list
[ (True <$ xs) ++ repeat False | xs <- xss])
> mapM_ print $ padAll '-' ["ommmmmmm", "ommmmmm", "ommmmm", "ommmm", "ommm",
"omm", "om", "o"]
"ommmmmmm"
"ommmmmm-"
"ommmmm--"
"ommmm---"
"ommm----"
"omm-----"
"om------"
"o-------"
You don't have to compare list lengths. Try to think about your zip function as a function taking only one argument xs and returning a function which will take ys and perform the required zip. Then, try to write a recursive function which recurses on xs only, as follows.
type Result = [Int] -> [(Int,Int)]
myZip :: [Int] -> Result
myZip [] = map (\y -> (0,y)) -- :: Result
myZip (x:xs) = f x (myZip xs) -- :: Result
where f x k = ??? -- :: Result
Once you have found f, notice that you can turn the recursion above into a fold!
As you said yourself, the standard zip :: [a] -> [b] -> [(a, b)] drops elements from the longer list. To amend for this fact you can modify your input before giving it to zip. First you will have to find out which list is the shorter one (most likely, using length). E.g.,
zip' x xs y ys | length xs <= length ys = ...
| otherwise = ...
where x is the default value for shorter xs and y the default value for shorter ys.
Then you extend the shorter list with the desired default elements (enough to account for the additional elements of the other list). A neat trick for doing so without having to know the length of the longer list is to use the function repeat :: a -> [a] that repeats its argument infinitely often.
zip' x xs y ys | length xs <= length ys = zip {-do something with xs-} ys
| otherwise = zip xs {-do something with ys-}
Here is another solution, that does work on infinite lists and is a straightforward upgrade of Prelude's zip functions:
zipDefault :: a -> b -> [a] -> [b] -> [(a,b)]
zipDefault _da _db [] [] = []
zipDefault da db (a:as) [] = (a,db) : zipDefault da db as []
zipDefault da db [] (b:bs) = (da,b) : zipDefault da db [] bs
zipDefault da db (a:as) (b:bs) = (a,b) : zipDefault da db as bs
and
zipDefaultWith :: a -> b -> (a->b->c) -> [a] -> [b] -> [c]
zipDefaultWith _da _db _f [] [] = []
zipDefaultWith da db f (a:as) [] = f a db : zipDefaultWith da db f as []
zipDefaultWith da db f [] (b:bs) = f da b : zipDefaultWith da db f [] bs
zipDefaultWith da db f (a:as) (b:bs) = f a b : zipDefaultWith da db f as bs
#pigworker, thank you for your enlightening solution!
Yet another implementation:
zipWithDefault :: a -> b -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithDefault dx _ f [] ys = zipWith f (repeat dx) ys
zipWithDefault _ dy f xs [] = zipWith f xs (repeat dy)
zipWithDefault dx dy f (x:xs) (y:ys) = f x y : zipWithDefault dx dy f xs ys
And also:
zipDefault :: a -> b -> [a] -> [b] -> [c]
zipDefault dx dy = zipWithDefault dx dy (,)
I would like to address the second part of Will Ness's solution, with its excellent use of known functions, by providing another to the original question.
zipPadWith :: a -> b -> (a -> b -> c) -> [a] -> [b] -> [c]
zipPadWith n _ f [] l = [f n x | x <- l]
zipPadWith _ m f l [] = [f x m | x <- l]
zipPadWith n m f (x:xs) (y:ys) = f x y : zipPadWith n m f xs ys
This function will pad a list with an element of choice. You can use a list of the same element repeated as many times as the number of lists in another like this:
rectangularWith :: a -> [[a]] -> [[a]]
rectangularWith _ [] = []
rectangularWith _ [ms] = [[m] | m <- ms]
rectangularWith n (ms:mss) = zipPadWith n [n | _ <- mss] (:) ms (rectangularWith n mss)
The end result will have been a transposed rectangular list of lists padded by the element that we provided so we only need to import transpose from Data.List and recover the order of the elements.
mapM_ print $ transpose $ rectangularWith 0 [[1,2,3,4],[5,6],[7,8],[9]]
[1,2,3,4]
[5,6,0,0]
[7,8,0,0]
[9,0,0,0]

Implementing filter using HoF in Haskell

I'm trying to write a function that takes a predicate f and a list and returns a list consisting of all items that satisfy f with preserved order. The trick is to do this using only higher order functions (HoF), no recursion, no comprehensions, and of course no filter.
You can express filter in terms of foldr:
filter p = foldr (\x xs-> if p x then x:xs else xs) []
I think you can use map this way:
filter' :: (a -> Bool) -> [a] -> [a]
filter' p xs = concat (map (\x -> if (p x) then [x] else []) xs)
You see? Convert the list in a list of lists, where if the element you want doesn't pass p, it turns to an empty list
filter' (> 1) [1 , 2, 3 ] would be: concat [ [], [2], [3]] = [2,3]
In prelude there is concatMap that makes the code simplier :P
the code should look like:
filter' :: (a -> Bool) -> [a] -> [a]
filter' p xs = concatMap (\x -> if (p x) then [x] else []) xs
using foldr, as suggested by sclv, can be done with something like this:
filter'' :: (a -> Bool) -> [a] -> [a]
filter'' p xs = foldr (\x y -> if p x then (x:y) else y) [] xs
You're obviously doing this to learn, so let me show you something cool. First up, to refresh our minds, the type of filter is:
filter :: (a -> Bool) -> [a] -> [a]
The interesting part of this is the last bit [a] -> [a]. It breaks down one list and it builds up a new list.
Recursive patterns are so common in Haskell (and other functional languages) that people have come up with names for some of these patterns. The simplest are the catamorphism and it's dual the anamorphism. I'll show you how this relates to your immediate problem at the end.
Fixed points
Prerequisite knowledge FTW!
What is the type of Nothing? Firing up GHCI, it says Nothing :: Maybe a and I wouldn't disagree. What about Just Nothing? Using GHCI again, it says Just Nothing :: Maybe (Maybe a) which is also perfectly valid, but what about the value that this a Nothing embedded within an arbitrary number, or even an infinite number, of Justs. ie, what is the type of this value:
foo = Just foo
Haskell doesn't actually allow such a definition, but with a slight tweak we can make such a type:
data Fix a = In { out :: a (Fix a) }
just :: Fix Maybe -> Fix Maybe
just = In . Just
nothing :: Fix Maybe
nothing = In Nothing
foo :: Fix Maybe
foo = just foo
Wooh, close enough! Using the same type, we can create arbitrarily nested nothings:
bar :: Fix Maybe
bar = just (just (just (just nothing)))
Aside: Peano arithmetic anyone?
fromInt :: Int -> Fix Maybe
fromInt 0 = nothing
fromInt n = just $ fromInt (n - 1)
toInt :: Fix Maybe -> Int
toInt (In Nothing) = 0
toInt (In (Just x)) = 1 + toInt x
This Fix Maybe type is a bit boring. Here's a type whose fixed-point is a list:
data L a r = Nil | Cons a r
type List a = Fix (L a)
This data type is going to be instrumental in demonstrating some recursion patterns.
Useful Fact: The r in Cons a r is called a recursion site
Catamorphism
A catamorphism is an operation that breaks a structure down. The catamorphism for lists is better known as a fold. Now the type of a catamorphism can be expressed like so:
cata :: (T a -> a) -> Fix T -> a
Which can be written equivalently as:
cata :: (T a -> a) -> (Fix T -> a)
Or in English as:
You give me a function that reduces a data type to a value and I'll give you a function that reduces it's fixed point to a value.
Actually, I lied, the type is really:
cata :: Functor T => (T a -> a) -> Fix T -> a
But the principle is the same. Notice, T is only parameterized over the type of the recursion sites, so the Functor part is really saying "Give me a way of manipulating all the recursion sites".
Then cata can be defined as:
cata f = f . fmap (cata f) . out
This is quite dense, let me elaborate. It's a three step process:
First, We're given a Fix t, which is a difficult type to play with, we can make it easier by applying out (from the definition of Fix) giving us a t (Fix t).
Next we want to convert the t (Fix t) into a t a, which we can do, via wishful thinking, using fmap (cata f); we're assuming we'll be able to construct cata.
Lastly, we have a t a and we want an a, so we just use f.
Earlier I said that the catamorphism for a list is called fold, but cata doesn't look much like a fold at the moment. Let's define a fold function in terms of cata.
Recapping, the list type is:
data L a r = Nil | Cons a r
type List a = Fix (L a)
This needs to be a functor to be useful, which is straight forward:
instance Functor (L a) where
fmap _ Nil = Nil
fmap f (Cons a r) = Cons a (f r)
So specializing cata we get:
cata :: (L x a -> a) -> List x -> a
We're practically there:
construct :: (a -> b -> b) -> b -> L a b -> b
construct _ x (In Nil) = x
construct f _ (In (Cons e n)) = f e n
fold :: (a -> b -> b) -> b -> List a -> b
fold f m = cata (construct f m)
OK, catamorphisms break data structures down one layer at a time.
Anamorphisms
Anamorphisms over lists are unfolds. Unfolds are less commonly known than there fold duals, they have a type like:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
As you can see anamorphisms build up data structures. Here's the more general type:
ana :: Functor a => (a -> t a) -> a -> Fix t
This should immediately look quite familiar. The definition is also reminiscent of the catamorphism.
ana f = In . fmap (ana f) . f
It's just the same thing reversed. Constructing unfold from ana is even simpler than constructing fold from cata. Notice the structural similarity between Maybe (a, b) and L a b.
convert :: Maybe (a, b) -> L a b
convert Nothing = Nil
convert (Just (a, b)) = Cons a b
unfold :: (b -> Maybe (a, b)) -> b -> List a
unfold f = ana (convert . f)
Putting theory into practice
filter is an interesting function in that it can be constructed from a catamorphism or from an anamorphism. The other answers to this question (to date) have also used catamorphisms, but I'll define it both ways:
filter p = foldr (\x xs -> if p x then x:xs else xs) []
filter p =
unfoldr (f p)
where
f _ [] =
Nothing
f p (x:xs) =
if p x then
Just (x, xs)
else
f p xs
Yes, yes, I know I used a recursive definition in the unfold version, but forgive me, I taught you lots of theory and anyway filter isn't recursive.
I'd suggest you look at foldr.
Well, are ifs and empty list allowed?
filter = (\f -> (>>= (\x -> if (f x) then return x else [])))
For a list of Integers
filter2::(Int->Bool)->[Int]->[Int]
filter2 f []=[]
filter2 f (hd:tl) = if f hd then hd:filter2 f tl
else filter2 f tl
I couldn't resist answering this question in another way, this time with no recursion at all.
-- This is a type hack to allow the y combinator to be represented
newtype Mu a = Roll { unroll :: Mu a -> a }
-- This is the y combinator
fix f = (\x -> f ((unroll x) x))(Roll (\x -> f ((unroll x) x)))
filter :: (a -> Bool) -> [a] -> [a]
filter =
fix filter'
where
-- This is essentially a recursive definition of filter
-- except instead of calling itself, it calls f, a function that's passed in
filter' _ _ [] = []
filter' f p (x:xs) =
if p x then
(x:f p xs)
else
f p xs