module General.ListBuilder(
    ListBuilder, runListBuilder, newListBuilder
    ) where

import Data.Semigroup (Semigroup (..))
import Data.Monoid hiding ((<>))
import Prelude()

data ListBuilder a
    = Zero
    | One a
    | Add (ListBuilder a) (ListBuilder a)


instance Semigroup (ListBuilder a) where
    Zero <> :: ListBuilder a -> ListBuilder a -> ListBuilder a
<> x :: ListBuilder a
x = ListBuilder a
x
    x :: ListBuilder a
x <> Zero = ListBuilder a
x
    x :: ListBuilder a
x <> y :: ListBuilder a
y = ListBuilder a -> ListBuilder a -> ListBuilder a
forall a. ListBuilder a -> ListBuilder a -> ListBuilder a
Add ListBuilder a
x ListBuilder a
y

instance Monoid (ListBuilder a) where
    mempty :: ListBuilder a
mempty = ListBuilder a
forall a. ListBuilder a
Zero
    mappend :: ListBuilder a -> ListBuilder a -> ListBuilder a
mappend = ListBuilder a -> ListBuilder a -> ListBuilder a
forall a. Semigroup a => a -> a -> a
(<>)

newListBuilder :: a -> ListBuilder a
newListBuilder :: a -> ListBuilder a
newListBuilder = a -> ListBuilder a
forall a. a -> ListBuilder a
One

runListBuilder :: ListBuilder a -> [a]
runListBuilder :: ListBuilder a -> [a]
runListBuilder x :: ListBuilder a
x = ListBuilder a -> [a] -> [a]
forall a. ListBuilder a -> [a] -> [a]
f ListBuilder a
x []
    where
        f :: ListBuilder a -> [a] -> [a]
f Zero acc :: [a]
acc = []
        f (One x :: a
x) acc :: [a]
acc = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
acc
        f (Add x :: ListBuilder a
x y :: ListBuilder a
y) acc :: [a]
acc = ListBuilder a -> [a] -> [a]
f ListBuilder a
x (ListBuilder a -> [a] -> [a]
f ListBuilder a
y [a]
acc)