Map Function using list implementation haskell - list

Is there a way to write an implementation of the Haskell map function using list implementation?
I keep getting an error and I do not think I am on the right track. This is what I have:
map' :: (a -> b) -> [a] -> [b]
map' _ [] = []
map' xs ys = [ (x, y) | x <- xs | y <- ys ]
Any help or link that will guide me in the right direction would be much appreciated.

I believe you mean "comprehension", instead of "implementation".
Either way, this would work:
map' f as = [f a | a <- as]
map' (* 2) [1..5]

Note that
map' f xs = [f x | x <- xs]
desugars to
map' f xs = do x <- xs
return $ f x
which desugars to
map' f xs = xs >>= return . f
which is the well-known definition (if you replace map' with fmap) for defining a Functor instance from a Monad instance (thus proving that all monads are also functors).
Specifically, it shows that a list comprehension is simply a disguised version of the definition of map in terms of monadic operators.

Related

Why are this two equivalents?

I don't quite understand why given two list of lists xss :: [[a]] and yss :: [[a]]
liftA2 (++) xss yss
is equivalent to
[xs ++ ys | xs <- xss, ys <- yss]
The reason is right here in the source code.
instance Applicative [] where
pure x = [x]
fs <*> xs = [f x | f <- fs, x <- xs]
liftA2 f xs ys = [f x y | x <- xs, y <- ys]
The liftA2 definition is an optimization, and we could also do it manually with the default definition of liftA2:
liftA2 f x y = f <$> x <*> y
So
liftA2 (++) xs ys
= (++) <$> xs <*> ys
= fmap (++) xs <*> ys -- definition of <$>
= [ f y | f <- fmap (++) xs, y <- ys ] -- definition of <*> above
= [ (++) x y | x <- xs, y <- ys ] -- some law about fmap/bind
= [ x ++ y | x <- xs, y <- ys ]
There you have it.
"Some law about fmap/bind" is this one:
fmap f x >>= t = x >>= t . f
which applies if you understand how list comprehensions are desugared. The proof is:
fmap f x >>= t
= x >>= pure . f >>= t -- fmap = liftM coherence
= x >>= (\y -> pure (f y) >>= t) -- definition of (.)
= x >>= (\y -> t (f y)) -- left unit monad law
= x >>= t . f -- definition of (.)
This is exactly the reason why i don't like using liftA<2..n> type of functions. They are an abstraction over the monad abstraction. It's just so because applicative is introduced after monads just to simplify to context of monads those contain functional values (functions).
Basically liftA2 (++) xs ys is (++) <$> xs <*> ys which makes more sense since it involves functor operator fmap in it's inline form <$>. Once you undertand the mechanics of the latter liftA2 starts to make sense.
fmap just applies the (++) function to the elements of the xs list (assume that xs is [[1,2],[3,4]]) and turns it into an applicative list (a list that contains functions) such as;
[([1,2] ++), ([3,4] ++)] :: Num a => [[a] -> [a]]
and the applicative operator <*> is now eligible to apply these functions in our list to another list which contains some other lists such as say, [[1,2],[3,4]].
At this very moment we have to know how exactly lists are handled monadically. Lists are undeterministic data types. So every single element of the first list has to be applied to the every single element of the second list. So
[([1,2] ++), ([3,4] ++)] <*> [[1,2],[3,4]]
turns out to be
[[1,2,1,2],[1,2,3,4],[3,4,1,2],[3,4,3,4]]
All in all liftA2 (++) just lifts the simple (++) function to the list monad. Simply saying, concatenate inner lists with each other monadically.
Having said that the list comprehensions version of this is a joke in Haskell. It is redundant and should be avoided in my honest opinion. It just takes a whole monad abstraction down to list level only whereas monadical approaches hold for all data types according to their appropriate monad instances.

Rewriting zipWith function using list comprehension

I've rewritten the zipWith function using recursion, and now I am trying to rewrite it using list comprehension. I have run into quite a few binding errors and I know that my second line is incorrect. This is the function I have that works like zipWith using recursion:
zipW :: (a -> b -> c) -> [a] -> [b] -> [c]
zipW _ [] _ = []
zipW _ _ [] = []
zipW f (x:xs) (y:ys) = f x y : zipW f xs ys
And this is my attempt to rewrite it as list comprehension:
zipW2 :: (a -> b -> c) -> [a] -> [b] -> [c]
zipW2 f xs ys = [f x y | (x, y) <- zipW2 f xs ys]
I am not sure how to correct the second statement so that it works like zipWith and allows me to choose the operator.
You will need Parallel List Comprehensions extension:
{-# LANGUAGE ParallelListComp #-}
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f xs ys = [f x y | x <- xs | y <- ys]
The original zipWith has three cases:
when the first list is empty
when the second list is empty
when the neither list is empty
The third case recursively calls zipWith on the tails of the arguments, which does the case analysis again.
In your definition, you only have one case - the list comprehension, so any recursive calls are going to wrap right back to that. And without case analysis, you could loop forever here:
>>> let myZipWith f xs ys = [ f x y | (x,y) <- myZipWith f xs ys ]
>>> myZipWith (,) [] []
^CInterrupted.
Furthermore because you're using f in the recursive call but requiring that the recursive output be a pair, you're placing the implicit requirement that f x y produce a pair:
>>> :t myZipWith
myZipWith :: (t2 -> t3 -> (t2, t3)) -> t -> t1 -> [(t2, t3)]
The solution is to not recurse, but instead to consider each pair directly.
You can use behzad.nouri's solution of enabling the ParallelListComp language extension:
>>> :set -XParallelListComp
>>> let myZipWith f xs ys = [ f x y | x <- xs | y <- ys ]
>>> myZipWith (+) [1,2,4] [0,10,20]
[1,12,24]
ParallelListComp makes the second (and later) vertical pipe characters (|) in a list comprehension legal syntax, stepping through those lists in parallel (zip-like) with earlier lists.
It's good to know how this differs from normal list comprehensions, where you separate each list you draw from with commas. Using commas does nested iteration which is flattened out in the resulting list:
>>> let notZipWith f xs ys = [ f x y | x <- xs, y <- ys ]
>>> notZipWith (+) [1,2,4] [0,10,20]
[1,11,21,2,12,22,4,14,24]
Using the ParallelListComp extension is really just syntatical sugar for the original zipWith, so you may consider it cheating.
You could also just rely on the original zip:
>>> let myZipWith f xs ys = [ f x y | (x,y) <- zip xs ys ]
>>> myZipWith (+) [1,2,4] [0,10,20]
[1,12,24]
But since zip is defined as zipWith (,), that's probably cheating too.
Another way you could go is to use indices:
>>> let myZipWith f xs ys = [ f x y | i <- [0..min (length xs) (length ys) - 1], let x = xs !! i, let y = ys !! i ]
>>> myZipWith (+) [1,2,4] [0,10,20]
[1,12,24]
But this is going to be horrendously inefficient, as !! is a linear-time operation, making myZipWith quadratic, while zipWith is linear:
>>> :set +s
>>> last $ myZipWith (+) (replicate 10000000 1) (replicate 10000000 2)
3
(4.80 secs, 3282337752 bytes)
>>> last $ zipWith (+) (replicate 10000000 1) (replicate 10000000 2)
3
(0.40 secs, 2161935928 bytes)
I'm sure there's other bad ways to create an equivalent to zipWith with a list comprehension, but I'm not terribly convinced that there's a good way, even from the ones above.

Haskell right-sided recursion to left-sided recursion

In my problem i have list of lists, and i want to find list of lists being selectors (selector - list containing exactly one element from each list), satisfying special condition.
The code to generate all selectors would look like:
selectors :: [[a]] -> [[a]]
selectors [] = [[]]
selectors (y:ys) = [ (x:xs) | x <- y, xs <- selectors ys]
If i wanted to add some extra condition this would be like
selectors :: [[a]] -> ([a] -> Bool) -> [[a]]
selectors [] _ = [[]]
selectors (y:ys) f = [ (x:xs) | x <- y, xs <- selectors ys f, f xs]
However in my problem, i need the condition to be dependable on element being candidate for a list, and what's in list i currently build. So this would be something like:
selectors :: [[a]] -> ( a-> [a] -> Bool) -> [[a]]
selectors [] _ = [[]]
selectors (y:ys) f = [ (x:xs) | x <- y, xs <- selectors ys f, f x xs]
And this is working very slow, because at first the recursion goes in very deeply and real work starts from there, whereas this would be MUCH faster if building list was going from left, so whenever i try to add new element to my list and i know this cannot be added so i'd just try to add new element. How can i make this work this way?
You can change the order of some searches by commuting the loop bodies.
for i in foo foo j in bar
for j in bar versus foo i in foo
do(i, j) do(i, j)
The same effect can be achieved in list comprehension syntax. For the given example, it might be
[ (x:xs) | x <- y, xs <- selectors ys f, f x xs ]
-- versus
[ (x:xs) | xs <- selectors ys f, x <- y, f x xs ]
If we're only considering the result as a set of values (i.e. the order is immaterial) then the values are identical. Regarded as a set, the only rules considering order of list comprehension clauses are that referenced variables must be bound in clauses left of their reference site.
Let's desugar this notation a bit to see the mechanics at work in higher fidelity.
List comprehensions are (almost) equivalent to do-notation in the list monad. Without necessarily diving into what monads are, I'll claim that our list comprehension desugars like this
-- [ (x:xs) | x <- y, xs <- selectors ys f, f x xs ]
-- becomes...
do x <- y
xs <- selectors ys f
guard (f x xs)
return (x:xs)
The translation should be obvious—each generator clause containing (<-) becomes a do-syntax binding form. Each guard clause becomes a do-notation form using the (perfectly normal) function guard :: Bool -> [()]. Finally, the translation preserves order.
But now, do-notation is just syntax sugar itself! It desugars to a series of function applications. Again, to not dive into the meaning of monads, I'll just do this transformation exactly.
-- [ (x:xs) | x <- y, xs <- selectors ys f, f x xs ]
-- becomes...
y >>= (\x -> selectors ys f >>= (\xs -> guard (f x xs) >> return (x:xs)))
In particular, each generator line like x <- E becomes E >>= (\x -> ...) where the ... corresponds to the translation of the remainder of the do block. Lines like E without binding arrows translate to E >> .... We can even simplify this one level further by noting that E >> F is nothing more than E >>= (\_ -> F) so that ultimately we have
y >>= (\x -> selectors ys f >>= (\xs -> guard (f x xs) >>= (\_ -> return (x:xs))))
And as a final step, we can translate the (>>=), guard, and return functions to the format they take for the list monad. In particular ls >>= f is equal to concat (map f ls) and return x = [x]. It's actually convenient to write (>>=) in a prefix instead of infix form, as well, so we'll call it forl :: [a] -> (a -> [b]) -> [b].
The function guard is a little strange. It looks like guard b = if b then [()] else []. We'll see how it works in a moment.
forl y $ \x ->
forl (selectors ys f) $ \xs ->
forl (guard (f x xs)) $ \_ ->
[x:xs]
Now this is a full translation. If we can understand this then we've understood the mechanics of the list comprehension. For comparison, this is how the list comprehension desugars when we switch the order of the generator clauses
forl y $ \x -> forl (selectors ys f) $ \xs ->
forl (selectors ys f) $ \xs -> forl y $ \x ->
forl (guard (f x xs)) $ \_ -> forl (guard (f x xs)) $ \_ ->
[x:xs] [x:xs]
which looks very similar to the imperative example given at the beginning. Let's show that it's actually identical.
First, we can dispatch how forl (guard (f x xs)) $ \_ -> [x:xs] works. We'll just inline the definition of guard and then forl
forl (if (f x xs) then [()] else []) (\_ -> [x:xs])
concat (map (\_ -> [x:xs]) (if (f x xs) then [()] else []))
We can "lift" the if out of the inside by noting that once we've wrapped the whole thing in an outer lift, the value of (f x xs) is fixed in both the then and else branches.
if (f x xs)
then concat (map (\_ -> [x:xs]) [()]
else concat (map (\_ -> [x:xs]) []
And finally, we can inline the maps and then the concats
if f x xs
then concat [(\_ -> [x:xs]) ()]
then concat []
if f x xs then [x:xs] else []
forl y $ \x -> forl (selectors ys f) $ \xs ->
forl (selectors ys f) $ \xs -> forl y $ \x ->
if f x xs then [x:xs] else [] if f x xs then [x:xs] else []
And now it ought to be increasingly clear how these "for" loops work. They loop over a body and produce a list of the results. Since we expect that the body will also be a forl loop, we have to anticipate that the value in the body is a list itself—this we flatten that extra layer of lists using concat.

Cartesian product of infinite lists in Haskell

I have a function for finite lists
> kart :: [a] -> [b] -> [(a,b)]
> kart xs ys = [(x,y) | x <- xs, y <- ys]
but how to implement it for infinite lists? I have heard something about Cantor and set theory.
I also found a function like
> genFromPair (e1, e2) = [x*e1 + y*e2 | x <- [0..], y <- [0..]]
But I'm not sure if it helps, because Hugs only gives out pairs without ever stopping.
Thanks for help.
Your first definition, kart xs ys = [(x,y) | x <- xs, y <- ys], is equivalent to
kart xs ys = xs >>= (\x ->
ys >>= (\y -> [(x,y)]))
where
(x:xs) >>= g = g x ++ (xs >>= g)
(x:xs) ++ ys = x : (xs ++ ys)
are sequential operations. Redefine them as alternating operations,
(x:xs) >>/ g = g x +/ (xs >>/ g)
(x:xs) +/ ys = x : (ys +/ xs)
[] +/ ys = ys
and your definition should be good to go for infinite lists as well:
kart_i xs ys = xs >>/ (\x ->
ys >>/ (\y -> [(x,y)]))
testing,
Prelude> take 20 $ kart_i [1..] [101..]
[(1,101),(2,101),(1,102),(3,101),(1,103),(2,102),(1,104),(4,101),(1,105),(2,103)
,(1,106),(3,102),(1,107),(2,104),(1,108),(5,101),(1,109),(2,105),(1,110),(3,103)]
courtesy of "The Reasoned Schemer". (see also conda, condi, conde, condu).
another way, more explicit, is to create separate sub-streams and combine them:
kart_i2 xs ys = foldr g [] [map (x,) ys | x <- xs]
where
g a b = head a : head b : g (tail a) (tail b)
this actually produces exactly the same results. But now we have more control over how we combine the sub-streams. We can be more diagonal:
kart_i3 xs ys = g [] [map (x,) ys | x <- xs]
where -- works both for finite
g [] [] = [] -- and infinite lists
g a b = concatMap (take 1) a
++ g (filter (not . null) (take 1 b ++ map (drop 1) a))
(drop 1 b)
so that now we get
Prelude> take 20 $ kart_i3 [1..] [101..]
[(1,101),(2,101),(1,102),(3,101),(2,102),(1,103),(4,101),(3,102),(2,103),(1,104)
,(5,101),(4,102),(3,103),(2,104),(1,105),(6,101),(5,102),(4,103),(3,104),(2,105)]
With some searching on SO I've also found an answer by Norman Ramsey with seemingly yet another way to generate the sequence, splitting these sub-streams into four areas - top-left tip, top row, left column, and recursively the rest. His merge there is the same as our +/ here.
Your second definition,
genFromPair (e1, e2) = [x*e1 + y*e2 | x <- [0..], y <- [0..]]
is equivalent to just
genFromPair (e1, e2) = [0*e1 + y*e2 | y <- [0..]]
Because the list [0..] is infinite there's no chance for any other value of x to come into play. This is the problem that the above definitions all try to avoid.
Prelude> let kart = (\xs ys -> [(x,y) | ls <- map (\x -> map (\y -> (x,y)) ys) xs, (x,y) <- ls])
Prelude> :t kart
kart :: [t] -> [t1] -> [(t, t1)]
Prelude> take 10 $ kart [0..] [1..]
[(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(0,9),(0,10)]
Prelude> take 10 $ kart [0..] [5..10]
[(0,5),(0,6),(0,7),(0,8),(0,9),(0,10),(1,5),(1,6),(1,7),(1,8)]
you can think of the sequel as
0: (0, 0)
/ \
1: (1,0) (0,1)
/ \ / \
2: (2,0) (1, 1) (0,2)
...
Each level can be expressed by level n: [(n,0), (n-1, 1), (n-2, 2), ..., (0, n)]
Doing this to n <- [0..]
We have
cartesianProducts = [(n-m, m) | n<-[0..], m<-[0..n]]

How to flatten a list non-recursively in sml/nj?

fun flat [] = []
| flat (l::ls) = l # flat ls;
This will flatten a list.
Is there a way to non recursively do the same operation? Perhaps with HOFs?
You could use high-order function List.foldr:
fun flat xs = List.foldr (fn (x, acc) => x # acc) [] xs
As #Andreas said, the function above can be shortened:
fun flat xs = List.foldr op# [] xs
Although you would like to implement flat as an exercise, List.concat in the standard library does exactly the same thing.