packages feed

fresnel-0.0.0.0: src/Fresnel/Monoid/Snoc.hs

{-# LANGUAGE RankNTypes #-}
module Fresnel.Monoid.Snoc
( -- * Snoc lists
  Snoc(..)
  -- * Construction
, singleton
, snoc
, nil
) where

import Data.Foldable (toList)

-- Snoc lists

newtype Snoc a = Snoc { runSnoc :: forall r . (r -> a -> r) -> r -> r }

instance Show a => Show (Snoc a) where
  showsPrec _ = showList . toList

instance Semigroup (Snoc a) where
  Snoc a1 <> Snoc a2 = Snoc (\ snoc -> a1 snoc . a2 snoc)

instance Monoid (Snoc a) where
  mempty = nil

instance Foldable Snoc where
  foldMap f (Snoc r) = r (const <> const f) mempty

instance Functor Snoc where
  fmap f (Snoc r) = r ((. f) . snoc) nil


-- Construction

singleton :: a -> Snoc a
singleton a = Snoc (\ snoc nil -> snoc nil a)

snoc :: Snoc a -> a -> Snoc a
snoc (Snoc as) a = Snoc (\ snoc nil -> snoc (as snoc nil) a)

nil :: Snoc a
nil = Snoc (\ _ nil -> nil)