{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTSyntax #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UnliftedNewtypes #-}
{-# LANGUAGE ViewPatterns #-}

module Data.Maybe.Void
  ( MaybeVoid# (..)
  , pattern JustVoid#
  , pattern NothingVoid#
  ) where

import GHC.Exts

{- | Unboxed variant of @Maybe@. The thing possibly contained by @Just@
has a void runtime representation. Rather than using a sum, like the
more general @Maybe#@ does, this represents @Nothing@ with 0 and
@Just@ with 1.

It is recommended that the data constructor not be used directly.
Prefer the two pattern synonyms.
-}
newtype MaybeVoid# :: TYPE ('TupleRep '[]) -> TYPE 'WordRep where
  MaybeVoid# :: forall (a :: TYPE ('TupleRep '[])). Word# -> MaybeVoid# a

pattern JustVoid# :: a -> MaybeVoid# a
pattern $mJustVoid# :: forall {r} {a :: ZeroBitType}.
MaybeVoid# a -> (a -> r) -> ((# #) -> r) -> r
$bJustVoid# :: forall (a :: ZeroBitType). a -> MaybeVoid# a
JustVoid# a <- (helper -> (# 1##, a #))
  where
    JustVoid# a
_ = Word# -> MaybeVoid# a
forall (a :: ZeroBitType). Word# -> MaybeVoid# a
MaybeVoid# Word#
1##

helper ::
  forall (a :: TYPE ('TupleRep '[])).
  MaybeVoid# a ->
  (# Word#, a #)
{-# INLINE helper #-}
helper :: forall (a :: ZeroBitType). MaybeVoid# a -> (# Word#, a #)
helper (MaybeVoid# Word#
x) =
  (# Word#
x, ((# #) -> a
forall a b. a -> b
unsafeCoerce# :: (# #) -> a) (# #) #)

pattern NothingVoid# :: MaybeVoid# a
pattern $mNothingVoid# :: forall {r} {a :: ZeroBitType}.
MaybeVoid# a -> ((# #) -> r) -> ((# #) -> r) -> r
$bNothingVoid# :: (# #) -> forall (a :: ZeroBitType). MaybeVoid# a
NothingVoid# = MaybeVoid# 0##