packages feed

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

{-# LANGUAGE RankNTypes #-}
module Fresnel.Monoid.Fork
( -- * Binary trees
  Fork(..)
  -- * Construction
, singleton
) where

import Control.Applicative (Alternative(..))
import Data.Foldable (toList)

-- Binary trees

newtype Fork a = Fork { runFork :: forall r . (r -> r -> r) -> (a -> r) -> r -> r }

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

instance Semigroup (Fork a) where
  Fork a1 <> Fork a2 = Fork (\ fork leaf nil -> a1 fork leaf nil `fork` a2 fork leaf nil)

instance Monoid (Fork a) where
  mempty = Fork (\ _ _ nil -> nil)

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

instance Functor Fork where
  fmap f (Fork r) = Fork (\ fork leaf -> r fork (leaf . f))

instance Applicative Fork where
  pure a = Fork (\ _ leaf _ -> leaf a)
  Fork f <*> Fork a = Fork (\ fork leaf nil -> f fork (\ f' -> a fork (leaf . f') nil) nil)

instance Alternative Fork where
  empty = mempty
  (<|>) = (<>)


-- Construction

singleton :: a -> Fork a
singleton a = Fork (\ _ leaf _ -> leaf a)