{-# LANGUAGE LambdaCase #-} {-# OPTIONS_GHC -Wall -fno-warn-tabs #-} module Data.Or ( Or(..), or, lefts, rights, fromLeft, fromRight, partitionOrs ) where import Prelude hiding (or) import Control.Arrow (first, second, (***)) data Or a b = L a | R b | LR a b deriving (Show, Read, Eq, Ord) or :: (a -> c) -> (b -> c) -> (a -> b -> c) -> Or a b -> c or f g h = \case L x -> f x; R y -> g y; LR x y -> h x y lefts :: [Or a b] -> [a] lefts [] = [] lefts (L x : os) = x : lefts os lefts (R _ : os) = lefts os lefts (LR x _ : os) = x : lefts os rights :: [Or a b] -> [b] rights [] = [] rights (L _ : os) = rights os rights (R y : os) = y : rights os rights (LR _ y : os) = y : rights os fromLeft :: a -> Or a b -> a fromLeft _ (L x) = x fromLeft d (R _) = d fromLeft _ (LR x _) = x fromRight :: b -> Or a b -> b fromRight d (L _) = d fromRight _ (R y) = y fromRight _ (LR _ y) = y partitionOrs :: [Or a b] -> ([a], [b]) partitionOrs [] = ([], []) partitionOrs (L x : os) = (x :) `first` partitionOrs os partitionOrs (R y : os) = (y :) `second` partitionOrs os partitionOrs (LR x y : os) = (x :) *** (y :) $ partitionOrs os