Skip to content

Instantly share code, notes, and snippets.

@edsko
Last active March 2, 2022 12:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edsko/a04cd80b0c4e783df9a652390a258619 to your computer and use it in GitHub Desktop.
Save edsko/a04cd80b0c4e783df9a652390a258619 to your computer and use it in GitHub Desktop.
-- | Alternate between @a@s and @b@s, starting and ending on a @a@
data Alternate a b =
AltDone a
| AltCons a b (Alternate a b)
instance Bifunctor Alternate where
bimap :: forall a a' b b'. (a -> a') -> (b -> b') -> Alternate a b -> Alternate a' b'
bimap f g = go
where
go :: Alternate a b -> Alternate a' b'
go (AltDone a) = AltDone (f a)
go (AltCons a b xs) = AltCons (f a) (g b) (go xs)
alternate :: forall a b. (a -> a -> b) -> NonEmpty a -> Alternate a b
alternate f (x :| xs) = go x xs
where
go :: a -> [a] -> Alternate a b
go a [] = AltDone a
go a (a':as) = AltCons a (f a a') (go a' as)
join :: forall a b. (a -> a -> b) -> Alternate a b -> Alternate a b -> Alternate a b
join f = go
where
go :: Alternate a b -> Alternate a b -> Alternate a b
go (AltDone a) (AltDone a') = AltCons a (f a a') (AltDone a')
go (AltDone a) ys@(AltCons a' _ _) = AltCons a (f a a') ys
go (AltCons a b xs) ys = AltCons a b (go xs ys)
joinMany :: forall a b. (a -> a -> b) -> NonEmpty (Alternate a b) -> Alternate a b
joinMany = foldr1 . join
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment