Skip to content

Instantly share code, notes, and snippets.

@joelburget
Created May 24, 2018 21:08
Show Gist options
  • Save joelburget/cfda3c526dbd2e6c62d3bf4a75462e22 to your computer and use it in GitHub Desktop.
Save joelburget/cfda3c526dbd2e6c62d3bf4a75462e22 to your computer and use it in GitHub Desktop.
{-# language LambdaCase #-}
module Data.Plur (Plur(..), count) where
import Data.Monoid
-- 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 Monoid (Plur a) where
mempty = Zero
mappend r1 Zero = r1
mappend Zero r2 = r2
mappend (One x) (One y) = Two x y
mappend (One x) (Two y _) = Two x y
mappend (Two x _) (One y) = Two x y
mappend (Two x _) (Two y _) = Two x y
count :: Plur a -> Int
count = \case
Zero -> 0
One _ -> 1
Two _ _ -> 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment