{-# language
  TypeApplications,
  ScopedTypeVariables
#-}

module Data.DifferenceList where

import Data.Coerce (coerce)
import Data.Foldable (Foldable (toList))

newtype DifferenceList a = DifferenceList ([a] -> [a])

instance Semigroup (DifferenceList a) where
  <> :: DifferenceList a -> DifferenceList a -> DifferenceList a
(<>) =
    forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @(([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]) -- ignore
      ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.)

instance Monoid (DifferenceList a) where
  mempty :: DifferenceList a
mempty =
    forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @([a] -> [a]) -- ignore
      [a] -> [a]
forall a. a -> a
id

instance Foldable DifferenceList where
  toList :: forall a. DifferenceList a -> [a]
toList (DifferenceList [a] -> [a]
differenceList) = [a] -> [a]
differenceList []
  foldr :: forall a b. (a -> b -> b) -> b -> DifferenceList a -> b
foldr a -> b -> b
f b
initial = (a -> b -> b) -> b -> [a] -> b
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> b -> b
f b
initial ([a] -> b) -> (DifferenceList a -> [a]) -> DifferenceList a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DifferenceList a -> [a]
forall a. DifferenceList a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

singleton :: a -> DifferenceList a
singleton :: forall a. a -> DifferenceList a
singleton = ([a] -> [a]) -> DifferenceList a
forall a. ([a] -> [a]) -> DifferenceList a
DifferenceList (([a] -> [a]) -> DifferenceList a)
-> (a -> [a] -> [a]) -> a -> DifferenceList a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)