-- |
-- Module      : Streamly.Internal.Data.Either.Strict
-- Copyright   : (c) 2019 Composewell Technologies
--               (c) 2013 Gabriel Gonzalez
-- License     : BSD3
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
-- | Strict data types to be used as accumulator for strict left folds and
-- scans. For more comprehensive strict data types see
-- https://hackage.haskell.org/package/strict-base-types . The names have been
-- suffixed by a prime so that programmers can easily distinguish the strict
-- versions from the lazy ones.
--
-- One major advantage of strict data structures as accumulators in folds and
-- scans is that it helps the compiler optimize the code much better by
-- unboxing. In a big tight loop the difference could be huge.
--
module Streamly.Internal.Data.Either.Strict
    ( Either' (..)
    -- XXX Remove these and add lazyEither/strictEither to convert to and from
    -- lazy Either type.
    , isLeft'
    , isRight'
    , fromLeft'
    , fromRight'
    )
where

-- | A strict 'Either'
data Either' a b = Left' !a | Right' !b deriving Int -> Either' a b -> ShowS
[Either' a b] -> ShowS
Either' a b -> String
(Int -> Either' a b -> ShowS)
-> (Either' a b -> String)
-> ([Either' a b] -> ShowS)
-> Show (Either' a b)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall a b. (Show a, Show b) => Int -> Either' a b -> ShowS
forall a b. (Show a, Show b) => [Either' a b] -> ShowS
forall a b. (Show a, Show b) => Either' a b -> String
$cshowsPrec :: forall a b. (Show a, Show b) => Int -> Either' a b -> ShowS
showsPrec :: Int -> Either' a b -> ShowS
$cshow :: forall a b. (Show a, Show b) => Either' a b -> String
show :: Either' a b -> String
$cshowList :: forall a b. (Show a, Show b) => [Either' a b] -> ShowS
showList :: [Either' a b] -> ShowS
Show

-- | Return 'True' if the given value is a Left', 'False' otherwise.
{-# INLINABLE isLeft' #-}
isLeft' :: Either' a b -> Bool
isLeft' :: forall a b. Either' a b -> Bool
isLeft' (Left'  a
_) = Bool
True
isLeft' (Right' b
_) = Bool
False

-- | Return 'True' if the given value is a Right', 'False' otherwise.
{-# INLINABLE isRight' #-}
isRight' :: Either' a b -> Bool
isRight' :: forall a b. Either' a b -> Bool
isRight' (Left'  a
_) = Bool
False
isRight' (Right' b
_) = Bool
True

-- XXX This is partial. We can use a default value instead.
-- | Return the contents of a Left'-value or errors out.
{-# INLINABLE fromLeft' #-}
fromLeft' :: Either' a b -> a
fromLeft' :: forall a b. Either' a b -> a
fromLeft' (Left' a
a) = a
a
fromLeft' Either' a b
_ = String -> a
forall a. HasCallStack => String -> a
error String
"fromLeft' expecting a Left'-value"

-- | Return the contents of a Right'-value or errors out.
{-# INLINABLE fromRight' #-}
fromRight' :: Either' a b -> b
fromRight' :: forall a b. Either' a b -> b
fromRight' (Right' b
b) = b
b
fromRight' Either' a b
_ = String -> b
forall a. HasCallStack => String -> a
error String
"fromRight' expecting a Right'-value"