lorentz-0.8.0: src/Lorentz/Iso.hs
-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ
-- | Isomorphisms in Lorentz.
module Lorentz.Iso
( LIso (..)
, invertIso
, involutedIso
, checkedCoerceIso
, forcedCoerceIso
, namedIso
, nonIso
, nonDefIso
) where
import Lorentz.Base
import Lorentz.Coercions
import Lorentz.Constraints
import Lorentz.Default
import Lorentz.Instr
import Lorentz.Macro
import Util.Label
import Util.Named
-- | Lorentz version of 'Control.Lens.Iso'.
data LIso a b = LIso
{ liTo :: forall s. a : s :-> b : s
, liFrom :: forall s. b : s :-> a : s
}
-- | Invert an isomorphism.
invertIso :: LIso a b -> LIso b a
invertIso LIso{..} = LIso{ liTo = liFrom, liFrom = liTo }
-- | Given a function that is its own inverse, make an 'LIso' using it
-- in both directions.
involutedIso :: Lambda a a -> LIso a a
involutedIso l = LIso (framed l) (framed l)
-- | The isomorphism between two values with identical representation
-- and semantics.
checkedCoerceIso :: Coercible_ a b => LIso a b
checkedCoerceIso = LIso checkedCoerce_ checkedCoerce_
-- | The isomorphism between two values with identical representation.
--
-- The same precautions as for 'forcedCoerce' apply here.
forcedCoerceIso :: MichelsonCoercible a b => LIso a b
forcedCoerceIso = LIso forcedCoerce_ forcedCoerce_
-- | The isomorphism between raw and named value.
namedIso :: Label n -> LIso a (n :! a)
namedIso l = LIso (toNamed l) (fromNamed l)
-- | Absence of value on the left hand side is associated with
-- the given value on the right hand side.
nonIso :: (NiceConstant a, NiceComparable a) => a -> LIso (Maybe a) a
nonIso defVal = LIso (fromOption defVal) (non defVal)
-- | Absence of value on the left hand side is associated with
-- the default value on the right hand side.
--
-- This is more general version of @nonIso ldef@ since it can
-- work with e.g. containers.
nonDefIso :: (LDefault a, NiceConstant a) => LIso (Maybe a) a
nonDefIso = LIso (fromOption ldef) (non' lIsDef)