packages feed

wireform-proto-0.2.0.0: src/Proto/Internal/Maybe.hs

-- Copyright © 2016 Kyle McKean
-- Copyright © 2018 Daniel Cartwright
-- BSD-3-Clause license (see LICENSE for full text)
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE UnboxedTuples #-}

{- | Unpacked Maybe using unboxed sums for zero-allocation optionals.

Internal module — public API boundaries convert to standard Maybe.
Uses GHC's @UnboxedTuples@ extension so the Just\/Nothing distinction
lives on the stack, not the heap.
-}
module Proto.Internal.Maybe (
  Maybe (Maybe, Just, Nothing),
  maybe,
  isJust,
  isNothing,
  fromBaseMaybe,
  toBaseMaybe,
) where

import Data.Function (const)
import Data.Maybe qualified as BaseMaybe
import GHC.Base (Bool (False, True))
import Prelude ()


data Maybe a = Maybe (# (# #) | a #)


pattern Just :: a -> Maybe a
pattern Just a = Maybe (# | a #)


pattern Nothing :: Maybe a
pattern Nothing = Maybe (# (# #) | #)


{-# COMPLETE Just, Nothing #-}


maybe :: b -> (a -> b) -> Maybe a -> b
maybe def f (Maybe x) = case x of
  (# (# #) | #) -> def
  (# | a #) -> f a
{-# INLINE maybe #-}


isJust :: Maybe a -> Bool
isJust = maybe False (const True)
{-# INLINE isJust #-}


isNothing :: Maybe a -> Bool
isNothing = maybe True (const False)
{-# INLINE isNothing #-}


fromBaseMaybe :: BaseMaybe.Maybe a -> Maybe a
fromBaseMaybe (BaseMaybe.Just x) = Just x
fromBaseMaybe BaseMaybe.Nothing = Nothing
{-# INLINE fromBaseMaybe #-}


toBaseMaybe :: Maybe a -> BaseMaybe.Maybe a
toBaseMaybe = maybe BaseMaybe.Nothing BaseMaybe.Just
{-# INLINE toBaseMaybe #-}