Michael Mossey mpm at alumni.caltech.edu
Mon Nov 2 06:43:25 EST 2009

```Another solution here. The inspiration is to try to use Data.Map's
fromListWith to do the main work. Notice that you can "decapitate" the
useless head of each list with the single line

dropWhile (not . both) . M.toAscList \$ neated

import Control.Arrow
import qualified Data.Map as M

data Combine v = LeftOnly v
| RightOnly v
| BothOfThem v v
deriving (Show)

cmb :: Combine a -> Combine a -> Combine a
cmb (LeftOnly x) (RightOnly y) = BothOfThem x y
cmb (RightOnly y) (LeftOnly x) = BothOfThem x y

both (_,(BothOfThem _ _ )) = True
both _ = False

chain _ last2 ((t,LeftOnly v):xs) = (t,(v,last2)) : chain v last2 xs
chain last1 _ ((t,RightOnly v):xs) = (t,(last1,v)) : chain last1 v xs
chain _ _     ((t,BothOfThem v w):xs) = (t,(v,w)) : chain v w xs
chain _ _     [] = []

specialZip d1 d2 =
let neated = M.fromListWith cmb \$ map (second LeftOnly) d1
++ map (second RightOnly) d2
dr = dropWhile (not . both) . M.toAscList \$ neated
in chain "" "" dr

Philip Scott wrote:
> Michael Mossey wrote:
>>
>> Function you seek is 'specialZip' below. 'fluff' and 'decapitate' are
>> helpers. Not extensively tested.
>
> Thanks Michael, that looks much better than mine :)
>
>
```