packages feed

spectacle-1.0.0: src/Language/Spectacle/Lang/Op.hs

{-# LANGUAGE EmptyCase #-}

-- | First-order effect operations.
--
-- @since 1.0.0
module Language.Spectacle.Lang.Op
  ( Op (OHere, OThere),
    decomposeOp,
    extractOp,
  )
where

-- -------------------------------------------------------------------------------------------------

-- | 'Op' is an extensible sum inhabited by a first-order effect @eff a@ in @effs@.
--
-- @since 1.0.0
data Op effs a where
  OHere :: eff a -> Op (eff ': effs) a
  OThere :: Op effs a -> Op (eff ': effs) a

-- | Orthogonal decomposition for 'Op'. Yields either a proof that the effect @eff@ is not
-- inhabiting the given 'Op' or a constructor for @eff@.
--
-- @since 1.0.0
decomposeOp :: Op (eff ': effs) a -> Either (Op effs a) (eff a)
decomposeOp (OHere eff) = Right eff
decomposeOp (OThere op) = Left op
{-# INLINE decomposeOp #-}

-- | A special case of 'decomposeOp'. A singleton sum of @eff@ must be inhabited by @eff@.
--
-- @since 1.0.0
extractOp :: Op '[eff] a -> eff a
extractOp (OHere eff) = eff
extractOp (OThere op) = case op of
{-# INLINE extractOp #-}