{-# LANGUAGE GADTs #-} {-# LANGUAGE LinearTypes #-} {-# LANGUAGE NoImplicitPrelude #-} -- | This module contains useful functions for working with 'Either's. module Data.Either.Linear ( Either (..), either, lefts, rights, fromLeft, fromRight, partitionEithers, ) where import Data.Unrestricted.Linear import Prelude (Either (..)) -- XXX Design Notes -- Functions like isLeft do not make sense in a linear program. -------------------------------------------------------------------------------- -- | Linearly consume an @Either@ by applying the first linear function on a -- value constructed with @Left@ and the second linear function on a value -- constructed with @Right@. either :: (a %1 -> c) -> (b %1 -> c) -> Either a b %1 -> c either f _ (Left x) = f x either _ g (Right y) = g y -- | Get all the left elements in order, and consume the right ones. lefts :: Consumable b => [Either a b] %1 -> [a] lefts [] = [] lefts (Left a : xs) = a : lefts xs lefts (Right b : xs) = lseq b (lefts xs) -- | Get all the right elements in order, and consume the left ones. rights :: Consumable a => [Either a b] %1 -> [b] rights [] = [] rights (Left a : xs) = lseq a (rights xs) rights (Right b : xs) = b : rights xs -- | Get the left element of a consumable @Either@ with a default fromLeft :: (Consumable a, Consumable b) => a %1 -> Either a b %1 -> a fromLeft x (Left a) = lseq x a fromLeft x (Right b) = lseq b x -- | Get the right element of a consumable @Either@ with a default fromRight :: (Consumable a, Consumable b) => b %1 -> Either a b %1 -> b fromRight x (Left a) = lseq a x fromRight x (Right b) = lseq x b -- | Partition and consume a list of @Either@s into two lists with all the -- lefts in one and the rights in the second, in the order they appeared in the -- initial list. partitionEithers :: [Either a b] %1 -> ([a], [b]) partitionEithers [] = ([], []) partitionEithers (x : xs) = fromRecur x (partitionEithers xs) where fromRecur :: Either a b %1 -> ([a], [b]) %1 -> ([a], [b]) fromRecur (Left a) (as, bs) = (a : as, bs) fromRecur (Right b) (as, bs) = (as, b : bs)