First you'll need a way to determine what constructor has been used:
isX :: Item -> Bool
isX (X _) = True
isX _ = False
-- If you have more than 2 constructors you'll have to write them all like isX
isY :: Item -> Bool
isY = not . isX
And a method to get the first value of each kind of constructor
import Data.Maybe
firstX :: [Item] -> Maybe Item
firstX = listToMaybe . filter isX
firstY :: [Item] -> Maybe Item
firstY = listToMaybe . filter isY
Then a way to replace items
replaceItem :: Item -> Maybe Item -> Item
replaceItem = fromMaybe
replaceItems :: [Item] -> Maybe Item -> Maybe Item -> [Item]
replaceItems [] _ _ = []
replaceItems (item:items) x y =
(if isX item
then replaceItem item x
else replaceItem item y) : replaceItems items x y
But since this is just a map:
replaceXY :: Item -> Maybe Item -> Maybe Item -> [Item]
replaceXY item x y =
if isX item
then replaceItem item x
else replaceItem item y
replaceItems items x y = map (\item -> replaceXY item x y) items
And finally you just have to combine this with firstX
and firstY
:
replaceFrom :: [Item] -> [Item] -> [Item]
replaceFrom a b =
let x = firstX b
y = firstY b
in replaceXY a x y