{-# LANGUAGE CPP #-}
------------------------------------------------------------------------
-- | Utilities for the 'Either' type
------------------------------------------------------------------------
module Agda.Utils.Either
( mapEither, mapLeft, mapRight
, isLeft, isRight
, allRight
, tests
) where
import Control.Arrow
import Agda.Utils.QuickCheck
import Agda.Utils.TestHelpers
#include "../undefined.h"
import Agda.Utils.Impossible
-- | 'Either' is a bifunctor.
mapEither :: (a -> c) -> (b -> d) -> Either a b -> Either c d
mapEither f g = either (Left . f) (Right . g)
-- | 'Either _ b' is a functor.
mapLeft :: (a -> c) -> Either a b -> Either c b
mapLeft f = mapEither f id
-- | 'Either a' is a functor.
mapRight :: (b -> d) -> Either a b -> Either a d
mapRight = mapEither id
-- | Returns 'True' iff the argument is @'Right' x@ for some @x@.
isRight :: Either a b -> Bool
isRight (Right _) = True
isRight (Left _) = False
-- | Returns 'True' iff the argument is @'Left' x@ for some @x@.
isLeft :: Either a b -> Bool
isLeft (Right _) = False
isLeft (Left _) = True
-- | Returns @'Right' @ if all elements are
-- to the right, and otherwise @Left @:
--
-- @
-- allRight xs ==
-- if all isRight xs then
-- Right (map (\(Right x) -> x) xs)
-- else
-- Left xs
-- @
allRight :: [Either a b] -> Either [Either a b] [b]
allRight [] = Right []
allRight xs@(Left _ : _) = Left xs
allRight (Right b : xs) = case allRight xs of
Left xs -> Left (Right b : xs)
Right bs -> Right (b : bs)
prop_allRight xs =
allRight xs ==
if all isRight xs then
Right (map fromRight xs)
else
Left xs
where
fromRight (Right x) = x
fromRight (Left _) = __IMPOSSIBLE__
------------------------------------------------------------------------
-- All tests
tests :: IO Bool
tests = runTests "Agda.Utils.Either"
[ quickCheck' (prop_allRight :: [Either Integer Bool] -> Bool)
]