Related
It is known that we can find head of a list using foldr like this:
head'' :: [a] -> a
head'' = foldr (\x _ -> x) undefined
but, is there any way to get the same result using foldl?
Similarly, we can find the last element of list using foldl like this:
last'' :: [a] -> a
last'' = foldl (\_ x -> x) undefined
Is there any way to get the same result using foldr?
head cannot be written with foldl, because foldl goes into an infinite loop on infinite lists, while head doesn't. Otherwise, sure:
head' :: [a] -> a
head' = fromJust . foldl (\y x -> y <|> Just x) Nothing
Drop the fromJust for a safe version.
last can definitely be written as a foldr, in about the same way:
last' :: [a] -> a
last' = fromJust . foldr (\x y -> y <|> Just x) Nothing
For head, we start with Nothing. The first element (the wanted one) is wrapped into Just and used to "override" the Nothing with (<|>). The following elements are ignored. For last, it's about the same, but flipped.
The first thing that springs to mind is to use foldl1 instead of foldl, then:
head'' :: [a] -> a
head'' = foldl1 (\x _ -> x)
and since foldl1 is defined in terms of foldl if the list is non-empty (and crashes if the list is empty - but so does head):
foldl1 f (x:xs) = foldl f x xs
we can say
head'' (x:xs) = foldl (\x _ -> x) x xs
The same of course for last, using foldr1
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.
I'm trying to write a function of the form
f :: String -> [String]
f str = ...
that returns the list of all the strings formed by removing exactly one character from str. For example:
ghci> f "stack"
["tack","sack","stck","stak","stac"]
Because String and [Char] are synonymous, I could use the index, but I know that you should avoid doing that in Haskell. Is there a better way besides using the index?
You could use recursion like so:
f :: [a] -> [[a]]
f [] = []
f (s:ss) = ss : map (s:) (f ss)
The Josh Kirklin's solution as a one-liner:
f = tail . foldr (\x ~(r:rs) -> (x : r) : r : map (x :) rs) [[]]
Maybe a more readable way to describe it is:
gaps :: [a] -> [[a]]
gaps xs = zipWith removeAt [0..] $ replicate (length xs) xs
removeAt i xs = ys ++ zs
where
(ys,_:zs) = splitAt i xs
But practically, it is slower than the other solutions.
I try to implement the reverse function with Maybe. I don't know how to return Just in pattern matching using recursion. By example, ghci> myReverse [1,2,3] need to return Just [3,2,1]. Here is my code :
myReverse :: [a] -> Maybe [a]
myReverse [] = Nothing
myReverse [x] = Just [x]
myReverse (x:xs) = myReverse xs ++ [x] -- here's my problem.
I thought that myReverse (x:xs) = Just $ myReverse xs ++ [x] work, but no and I don't know how to do it. What I would to know it is how to do it and why.
Thanks for your help!
myReverse returns a Maybe [a], which can't be directly appended to something because it is not a list. IOW the value of myReverse xs will be either Nothing, or Just <some list>. You need to pattern match on the result.
myReverse (x:xs) =
case myReverse xs of
Just list -> ...
Nothing -> ...
And of course, you need to decide what needs to be done in each of these cases, depending on what you want myReverse to do.
Also keep in mind that not every function needs to be recursive, so you can call the regular reverse from myReverse if you need it.
As [a] is a Monoid define by,
instance Monoid [a] where
mempty = []
mappend = (++)
Then Maybe [a] is also a Monoid,
instance Monoid a => Monoid (Maybe a) where
mempty = Nothing
Nothing `mappend` m = m
m `mappend` Nothing = m
Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
Note the type constraint in the instance declaration which impose a to be a Monoid or else Maybe a won't.
We can then use mappend, (<>), to chain our recursive call at the condition to transform the head of the list to a singleton.
import Data.Monoid ((<>))
myReverse :: [a] -> Maybe [a]
myReverse [] = Nothing
myReverse (x:xs) = myReverse xs <> Just [x]
Last note, the previous fold solution can be improve too.
>>> let mrev = foldl' (\x y -> Just [y] <> x ) Nothing
>>> mrev []
Nothing
>>> mrev "hello"
Just "olleh"
Previous fold answer
Knowing that reverse can be define using fold as follow,
>>> foldl' (flip (:)) [] [1..5]
[5,4,3,2,1]
This can be rewritten as,
>>> foldl' (\x y -> y:x) [] [1..5]
[5,4,3,2,1]
To adapt for Maybe type, we do the following transformation,
The seed [] become (Just [])
The anonymous function must now be apply inside Just, we use fmap to do it.
This lead us to,
>>> foldl' (\x y -> fmap (y:) x) (Just []) [1..5]
Just [5,4,3,2,1]
Finally,
mreverse xs | null xs = Nothing
| foldl' (\x y -> fmap (y:) x) (Just []) xs
I thought of something along the lines of luqui's, except applying the Maybe at the end:
myReverse :: [a] -> Maybe [a]
myReverse ys
| null (myReverse' ys) = Nothing
| otherwise = Just (myReverse' ys)
where
myReverse' [] = []
myReverse' (x:xs) = myReverse' xs ++ [x]
Or, if you will,
myReverse ys | null (reverse ys) = Nothing
| otherwise = Just (reverse ys)
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