Skip to content

Instantly share code, notes, and snippets.

@safareli
Last active September 26, 2019 09:55
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 safareli/e04a277d5662490b4d37bb0c0412b05f to your computer and use it in GitHub Desktop.
Save safareli/e04a277d5662490b4d37bb0c0412b05f to your computer and use it in GitHub Desktop.
data Count = One | Two | ThreeOrMore
type Datum = { count :: Count, char :: Char }
data Stat = Stat (Array Datum)
instance semigroupCount :: Semigroup Count where
append One One = Two
append One _ = ThreeOrMore
append Two _ = ThreeOrMore
toStat :: Char -> Stat
toStat = Stat [{ count: One, char: _ }]
fromDatum :: Datum -> [Char]
fromDatum {count, char} = case count of
One -> [char]
Two -> [char, char]
ThreeOrMore -> []
instance semigroupStat :: Semigroup Stat where
append (Stat a) (Stat b) = case Array.unsnoc a of
Nothing -> Stat b -- a is empty
Just { init, last } -> case Array.uncons b of
Nothing -> Stat a -- b is empty
Just { head, tail }
| last.char == head.char ->
let count = append last.count head.count
in if count == ThreeOrMore
then append (Stat init) (Stat tail) -- recursive call
else (Stat (init <> [{ count, char: head.char }] <> tail)
| otherwise -> Stat (append a b)
instance monoidStat :: Monoid Stat where
mempty = Stat []
compute :: [Char] -> [Char]
compute = foldMap toDatum >>> un Stat >>> foldMap fromDatum
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment