module Data.Plur (Plur(..), count) where
import Control.Applicative
import Data.Foldable
import Data.Monoid
import Data.Semigroup as Semigroup
import Data.Traversable
data Plur a
= Zero
| One !a
| Two !a !a
deriving (Show, Eq, Ord)
instance Functor Plur where
fmap f plur = case plur of
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 `mappend` fmap f2 x
instance Monad Plur where
return = pure
x >>= f = case x of
Zero -> Zero
One x1 -> f x1
Two x1 x2 -> f x1 `mappend` f x2
instance Foldable Plur where
foldMap f plur = case plur of
Zero -> mempty
One a -> f a
Two a1 a2 -> f a1 `mappend` f a2
instance Traversable Plur where
traverse f plur = case plur of
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 y <> _ = Two x y
instance Monoid (Plur a) where
mempty = Zero
mappend = (Semigroup.<>)
count :: Plur a -> Int
count plur = case plur of
Zero -> 0
One _ -> 1
Two _ _ -> 2