plur-0.1.0.0: src/Data/Plur.hs
{-# language LambdaCase #-}
module Data.Plur (Plur(..), count) where
import Data.Monoid
import Data.Semigroup
-- Plurality monad: Zero, one, or at least two.
data Plur a
= Zero
| One a
| Two a a
deriving (Show, Eq, Ord)
instance Functor Plur where
fmap f = \case
Zero -> Zero
One a -> One (f a)
Two a1 a2 -> Two (f a1) (f a2)
instance Applicative Plur where
pure = One
(<*>) Zero _ = Zero
(<*>) _ Zero = Zero
(<*>) (One f) x = fmap f x
(<*>) (Two f1 f2) x = fmap f1 x <> fmap f2 x
instance Monad Plur where
(>>=) x f = case x of
Zero -> Zero
One x1 -> f x1
Two x1 x2 -> f x1 <> f x2
instance Foldable Plur where
foldMap f = \case
Zero -> mempty
One a -> f a
Two a1 a2 -> f a1 <> f a2
instance Traversable Plur where
traverse f = \case
Zero -> pure Zero
One a -> One <$> f a
Two a1 a2 -> Two <$> f a1 <*> f a2
instance Semigroup (Plur a) where
r1 <> Zero = r1
Zero <> r2 = r2
One x <> One y = Two x y
One x <> Two y _ = Two x y
Two x _ <> One y = Two x y
Two x _ <> Two y _ = Two x y
instance Monoid (Plur a) where
mempty = Zero
count :: Plur a -> Int
count = \case
Zero -> 0
One _ -> 1
Two _ _ -> 2