I am trying to write a function join :: [[a]] -> [[a]]
that joins the last character of a list within a list with the first character of a list within a list.
join ["m"] = ["m"]
join ["a","b","c"] = ["b","c","a"]
join ["goodday", "world", "i", "love", "haskell"] = ["ooddayw","orldi","l","oveh","askellg"]
join ["the", "catcher", "in", "the", "rye"] = ["hec","atcheri","nt","her","yet"]
I am trying to write a code that does the above using only the basic functions in Haskell (no library functions), and only using recursion.
However, I cannot seem to achieve a piece of code that works appropriately. This is the code that I have so far:
join :: [[a]] -> [[a]]
join [[a]] = [[a]]
join (n:ns:nss) | null nss == False = ((i n ns) : k (ns:nss))
| otherwise = []
Is it possible to do this?
CodePudding user response:
Here's a solution with higher-order functions, working in the whole data-manipulation paradigm:
import Control.Applicative (liftA2)
import Data.List (unfoldr)
import Control.Arrow ( (>>>) )
rotateds :: [[a]] -> [[a]]
rotateds =
map (splitAt 1) -- 1., 2.,
>>> concatMap (\(a,b) -> [a,b]) -- 3.,
>>> liftA2 ( ) (drop 1) (take 1) -- 4.,
>>> unfoldr (Just . splitAt 2) -- 5.,
>>> takeWhile (not . null) -- 5.,
>>> map (\[a,b] -> ( ) a b) -- 6.
It passes all your tests. So yes it is possible. How it works is:
1. turn each sublist in the input [ [a,b,c,...] , [d,......] , ... ]
2. into a pair [ ([a],[b,c,...]) , ([d], [...]) , ... ]
3. splice'em in [ [a],[b,c,...] , [d], [...] , ... ]
4. move the first letter over [ [b,c,...] , [d], ........ [a] ]
5. and restore the structure back to how it was
by reconstituting the pairs [ [[b,c,...] , [d]], ........... ]
6. and appending them together [ [ b,c,... , d ], ........... ]
Converting it to straight manual recursion is a torturous task is left as an exercise for an avid learner.