haskell language concatenation - list

this is my assignment the string concatenation function is below and below that is the function that i need help with.
type Language = [String]
strcat :: String -> String -> String
strcat [] y = y
strcat (x:xs) y = x:(strcat xs y)
concat_lang :: Language -> Language -> Language
concat_lang [] y = y
concat_lang x [] = x
concat_lang (x:xs) (y:ys) = (strcat x y):(concat_lang (x:xs) ys)
This is my input to concat_lang : concat_lang ["a","b","c"] ["d","e","f"]
i want the output to be [ad,ae,af,bd,be,bf,cd,ce,cf]
Pls help!!

List comprehension makes life much easier
lang xs ys = [x:y:[] | x <- xs , y <- ys]
lang is polymorphic, if this is undesirable, simply add a type signature.

combinations :: [a] -> [b] -> [(a,b)]
combinations xs ys = concatMap (flip zip ys . repeat) xs
type Language = [String]
concat_lang :: Language -> Language -> Language
concat_lang xs ys = map f $ combinations xs ys
where
f (x,y) = x ++ y
use
concat_lang ["a","b","c"] ["d","e","f"]
to get
["ad","ae","af","bd","be","bf","cd","ce","cf"]

concat_lang xs ys = [ x++y | x <- xs, y <- ys]

Classic example where Applicative Functors can come in handy:
>> import Control.Applicative
>> (++) <$> ["a", "b", "c"] <*> ["d", "e", "f"]
["ad","ae","af","bd","be","bf","cd","ce","cf"]
>>
You should definitely check out Aplicative Functors for this ...

Related

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.

How to insert a list in a list in all possible ways?

I am trying to enumerate all the possible merges of two lists.
In example inserting "bb" into "aaa" would look like
["bbaaa", "babaa", "baaba", "baaab", "abbaa", "ababa", "abaab", "aabba", "aabab", "aaabb"]
What I currently did is this
import Data.List
insert'' :: Char -> String -> [(String, String)] -> String
insert'' _ _ ([]) = []
insert'' h b ((x, y):xs) =
(x ++ [h] ++ (insert' (b, y))) ++ (insert'' h b xs)
insert' :: (String, String) -> String
insert' ([], ys) = ys
insert' (xs, ys) =
insert'' h b lists
where
h = head xs
b = tail xs
lists = zip (tails ys) (inits ys)
This returns for ("aaa", "bb")
"bbaaababaaabaababbaababaababbabababb"
a concatenated string, I tried making it a list of strings, but I just cannot wrap my head around this function. I always seems to get infinite type construction.
How could I rewrite the function, so it would return a list of strings?
An other implementation idea as in Daniel Wagners first post is to choose in each step a element from one of the lists and prepending it to the results generated by the function called with only the remaining parts of the list:
interleave :: [a] -> [a] -> [[a]]
interleave xs [] = [xs]
interleave [] ys = [ys]
interleave xs#(x : xs') ys#(y : ys') =
map (x :) (interleave xs' ys) ++ map (y :) (interleave xs ys')
For your intial example this produces:
ghci> interleave "bb" "aaa"
["bbaaa","babaa","baaba","baaab","abbaa","ababa","abaab","aabba","aabab","aaabb"]
Here is one implementation idea: for each element in the first list, we will choose (nondeterministically) a position in the second list to insert it, then recurse. For this to work, we first need a way to nondeterministically choose a position; thus:
choose :: [a] -> [([a], [a])]
choose = go [] where
go before xs = (before, xs) : case xs of
[] -> []
x:xs -> go (x:before) xs
For example:
> choose "abcd"
[("","abcd"),("a","bcd"),("ba","cd"),("cba","d"),("dcba","")]
Now we can use this tool to do the insertion:
insert :: [a] -> [a] -> [[a]]
insert [] ys = [ys]
insert (x:xs) ys = do
(before, after) <- choose ys
rest <- insert xs (reverse after)
return (before ++ [x] ++ rest)
In ghci:
> insert "ab" "cde"
["abcde","aebcd","adebc","acdeb","cabde","caebd","cadeb","dcabe","dcaeb","edcab"]
In this answer, I will give the minimal change needed to fix the code you already have (without completely rewriting your code). The first change needed is to update your type signatures to return lists of strings:
insert'' :: Char -> String -> [(String, String)] -> [String]
insert' :: (String, String) -> [String]
Now your compiler will complain that the first clause of insert' is returning a String instead of a [String], which is easily fixed:
insert' ([], ys) = [ys]
...and that the second clause of insert'' is trying to append a String to a [String] when running [h] ++ insert' (b, y). This one takes some thinking to figure out what you really meant; but my conclusion is that instead of x ++ [h] ++ insert' (b, y), you really want to run \t -> x ++ [h] ++ t for each element in insert' (b, y). Thus:
insert'' h b ((x, y):xs) =
(map (\t -> x ++ [h] ++ t) (insert' (b, y))) ++ (insert'' h b xs)
The complete final code is:
import Data.List
insert'' :: Char -> String -> [(String, String)] -> [String]
insert'' _ _ ([]) = []
insert'' h b ((x, y):xs) =
(map (\t -> x ++ [h] ++ t) (insert' (b, y))) ++ (insert'' h b xs)
insert' :: (String, String) -> [String]
insert' ([], ys) = [ys]
insert' (xs, ys) =
insert'' h b lists
where
h = head xs
b = tail xs
lists = zip (tails ys) (inits ys)
Now ghci will happily produce good answers:
> insert' ("aaa", "bb")
["bbaaa","babaa","baaba","baaab","abbaa","ababa","abaab","aabba","aabab","aaabb"]

Monadic way for list comprehension

I have the following function
combinations :: [[a]] -> [[a]]
combinations [] = [[]]
combinations (xs:xss) = concat [map (x:) yss | x <- xs]
where yss = combinations xss
Which produces all combinations between its elements:
*Main> combinations [[1,2],[2,3,4],[5,6]]
[[1,2,5],[1,2,6],[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,2,5],[2,2,6],[2,3,5],[2,3,6]
,[2,4,5],[2,4,6]]
I some how feel there must be a monadic way to do this
foobar = do
n <- [1,2]
ch <- [3,4,5]
return[n,ch]
This is how far I came. But I am stuck.
Your function is sequence for the list monad.
> :t sequence
sequence :: Monad m => [m a] -> m [a]
> sequence [[1,2],[2,3,4],[5,6]]
[[1,2,5],[1,2,6],[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,2,5],[2,2,6],[2,3,5],[2,3,6],
[2,4,5],[2,4,6]]
The best I've been able to come up with is
combinations [] = [[]]
combinations (xs:xss) = do
x <- xs
ys <- combinations xss
return $ x : ys
The way I derived this was I first converted the list comprehension into monadic code (which also meant dropping the concat to get it to type check)
combinations (xs:xss) =
let yss = combinations xss
in do
x <- xs
map (x:) yss
Then I realized that map (x:) yss is exactly fmap (x:) yss, which is exactly yss >>= return . (x:), so I knew I could do
combinations (xs:xss) =
let yss = combinations xss
in do
x <- xs
ys <- yss
return $ x : ys
And then it can be inlined as
combinations (xs:xss) = do
x <- xs
ys <- combinations xss
return $ x : ys

Implement insert in haskell with foldr

How to implement insert using foldr in haskell.
I tried:
insert'' :: Ord a => a -> [a] -> [a]
insert'' e xs = foldr (\x -> \y -> if x<y then x:y else y:x) [e] xs
No dice.
I have to insert element e in list so that it goes before first element that is larger or equal to it.
Example:
insert'' 2.5 [1,2,3] => [1.0,2.0,2.5,3.0]
insert'' 2.5 [3,2,1] => [2.5,3.0,2.0,1.0]
insert'' 2 [1,2,1] => [1,2,2,1]
In last example first 2 is inserted one.
EDIT:
Thanks #Lee.
I have this now:
insert'' :: Ord a => a -> [a] -> [a]
insert'' e xs = insert2 e (reverse xs)
insert2 e = reverse . snd . foldr (\i (done, l) -> if (done == False) && (vj e i) then (True, e:i:l) else (done, i:l)) (False, [])
where vj e i = e<=i
But for this is not working:
insert'' 2 [1,3,2,3,3] => [1,3,2,2,3,3]
insert'' 2 [1,3,3,4] => [1,3,2,3,4]
insert'' 2 [4,3,2,1] => [4,2,3,2,1]
SOLUTION:
insert'' :: Ord a => a -> [a] -> [a]
insert'' x xs = foldr pom poc xs False
where
pom y f je
| je || x > y = y : f je
| otherwise = x : y : f True
poc True = []
poc _ = [x]
Thanks #Pedro Rodrigues (It just nedded to change x>=y to x>y.)
(How to mark this as answered?)
You need paramorphism for that:
para :: (a -> [a] -> r -> r) -> r -> [a] -> r
foldr :: (a -> r -> r) -> r -> [a] -> r
para c n (x : xs) = c x xs (para c n xs)
foldr c n (x : xs) = c x (foldr c n xs)
para _ n [] = n
foldr _ n [] = n
with it,
insert v xs = para (\x xs r -> if v <= x then (v:x:xs) else (x:r)) [v] xs
We can imitate paramorphisms with foldr over init . tails, as can be seen here: Need to partition a list into lists based on breaks in ascending order of elements (Haskell).
Thus the solution is
import Data.List (tails)
insert v xs = foldr g [v] (init $ tails xs)
where
g xs#(x:_) r | v <= x = v : xs
| otherwise = x : r
Another way to encode paramorphisms is by a chain of functions, as seen in the answer by Pedro Rodrigues, to arrange for the left-to-right information flow while passing a second copy of the input list itself as an argument (replicating the effect of tails):
insert v xs = foldr g (\ _ -> [v]) xs xs
where
g x r xs | v > x = x : r (tail xs) -- xs =#= (x:_)
| otherwise = v : xs
-- visual aid to how this works, for a list [a,b,c,d]:
-- g a (g b (g c (g d (\ _ -> [v])))) [a,b,c,d]
Unlike the version in his answer, this does not copy the rest of the list structure after the insertion point (which is possible because of paramorphism's "eating the cake and having it too").
Here's my take at it:
insert :: Ord a => a -> [a] -> [a]
insert x xs = foldr aux initial xs False
where
aux y f done
| done || x > y = y : f done
| otherwise = x : y : f True
initial True = []
initial _ = [x]
However IMHO using foldr is not the best fit for this problem, and for me the following solution is easier to understand:
insert :: Int -> [Int] -> [Int]
insert x [] = [x]
insert x z#(y : ys)
| x <= y = x : z
| otherwise = y : insert x ys
I suppose fold isn't handy here. It always processes all elements of list, but you need to stop then first occurence was found.
Of course it is possible, but you probable don't want to use this:
insert' l a = snd $ foldl (\(done, l') b -> if done then (True, l'++[b]) else if a<b then (False, l'++[b]) else (True, l'++[a,b])) (False, []) l

Mixing pattern matching and currying in OCaml

In SML, it's common and easy to define a function using both currying and pattern matching. Here's a simple example:
fun zip [] _ = []
| zip _ [] = []
| zip (x::xs) (y::ys) = (x,y)::(zip xs ys)
Ignoring library functions, what's the best way to port this to OCaml? As far as I can tell, there is no easy way to declare a function using both currying and pattern matching.
I would say it's best to just use a match expression.
let rec zip xs ys =
match xs, ys with
| [], _
| _, [] -> []
| x :: xs, y :: ys -> (x, y) :: zip xs ys
If you're set on not using match, it's a bit convoluted, but you can do this.
let rec zip = function
| [] -> (fun _ -> [])
| x :: xs ->
function
| [] -> []
| y :: ys -> (x, y) :: zip xs ys