left' ≡ dimap swapE swapE . right' where swapE :: Either a b -> Either b a swapE = either Right Left rmap Left ≡ lmap Left . left' lmap (right f) . left' ≡ rmap (right f) . left' left' . left' ≡ dimap assocE unassocE . left' where assocE :: Either (Either a b) c -> Either a (Either b c) assocE (Left (Left a)) = Left a assocE (Left (Right b)) = Right (Left b) assocE (Right c) = Right (Right c) unassocE :: Either a (Either b c) -> Either (Either a b) c unassocE (Left a) = Left (Left a) unassocE (Right (Left b)) = Left (Right b) unassocE (Right (Right c)) = Right c
leftToMaybe ≡ either Just (const Nothing)Using Control.Lens:
leftToMaybe ≡ preview _Left leftToMaybe x ≡ x^?_Left
>>> leftToMaybe (Left 12) Just 12
>>> leftToMaybe (Right 12) Nothing
>>> fromLeft 1 (Left 3) 3 >>> fromLeft 1 (Right "foo") 1
>>> isLeft (Left "foo") True >>> isLeft (Right 3) FalseAssuming a Left value signifies some sort of error, we can use isLeft to write a very simple error-reporting function that does absolutely nothing in the case of success, and outputs "ERROR" if any error occurred. This example shows how isLeft might be used to avoid pattern matching when one does not care about the value contained in the constructor:
>>> import Control.Monad ( when ) >>> let report e = when (isLeft e) $ putStrLn "ERROR" >>> report (Right 1) >>> report (Left "parse error") ERROR
unleft ≡ unright . dimap swapE swapE where swapE :: Either a b -> Either b a swapE = either Right Left rmap (either id absurd) ≡ unleft . lmap (either id absurd) unfirst . rmap (second f) ≡ unfirst . lmap (second f) unleft . unleft ≡ unleft . dimap assocE unassocE where assocE :: Either (Either a b) c -> Either a (Either b c) assocE (Left (Left a)) = Left a assocE (Left (Right b)) = Right (Left b) assocE (Right c) = Right (Right c) unassocE :: Either a (Either b c) -> Either (Either a b) c unassocE (Left a) = Left (Left a) unassocE (Right (Left b)) = Left (Right b) unassocE (Right (Right c)) = Right c