{-# LANGUAGE FunctionalDependencies #-}
module Lorentz.Referenced
( dupT
, dipT
, dropT
) where
import Prelude hiding (drop, swap)
import GHC.TypeLits (ErrorMessage(..), TypeError)
import Lorentz.Base
import Lorentz.Constraints
import Lorentz.Instr
import Lorentz.Value
import Morley.Util.Type
type family StackElemNotFound st a :: ErrorMessage where
StackElemNotFound st a =
'Text "Element of type `" ':<>: 'ShowType a ':<>:
'Text "` is not present on stack" ':$$: 'ShowType st
type family StackElemAmbiguous st a :: ErrorMessage where
StackElemAmbiguous st a =
'Text "Ambigous reference to element of type `" ':<>: 'ShowType a ':<>:
'Text "` for stack" ':$$: 'ShowType st
class DupT (origSt :: [Type]) (a :: Type) (st :: [Type]) where
dupTImpl :: st :-> a : st
instance TypeError (StackElemNotFound origSt a) =>
DupT origSt a '[] where
dupTImpl :: '[] :-> '[a]
dupTImpl = Text -> '[] :-> '[a]
forall a. HasCallStack => Text -> a
error Text
"impossible"
instance {-# OVERLAPPING #-}
( If (a `IsElem` st)
(TypeError (StackElemAmbiguous origSt a))
(() :: Constraint)
, Dupable a
) =>
DupT origSt a (a : st) where
dupTImpl :: (a : st) :-> (a : a : st)
dupTImpl = (a : st) :-> (a : a : st)
forall a (s :: [*]). Dupable a => (a : s) :-> (a : a : s)
dup
instance {-# OVERLAPPABLE #-}
DupT origSt a st =>
DupT origSt a (b : st) where
dupTImpl :: (b : st) :-> (a : b : st)
dupTImpl = (st :-> (a : st)) -> (b : st) :-> (b : a : st)
forall a (s :: [*]) (s' :: [*]).
HasCallStack =>
(s :-> s') -> (a : s) :-> (a : s')
dip (forall (origSt :: [*]) a (st :: [*]).
DupT origSt a st =>
st :-> (a : st)
dupTImpl @origSt) ((b : st) :-> (b : a : st))
-> ((b : a : st) :-> (a : b : st)) -> (b : st) :-> (a : b : st)
forall (a :: [*]) (b :: [*]) (c :: [*]).
(a :-> b) -> (b :-> c) -> a :-> c
# (b : a : st) :-> (a : b : st)
forall a b (s :: [*]). (a : b : s) :-> (b : a : s)
swap
dupT :: forall a st. DupT st a st => st :-> a : st
dupT :: forall a (st :: [*]). DupT st a st => st :-> (a : st)
dupT = forall (origSt :: [*]) a (st :: [*]).
DupT origSt a st =>
st :-> (a : st)
dupTImpl @st @a @st
_dupSample1 :: [Integer, MText, ()] :-> [MText, Integer, MText, ()]
_dupSample1 :: '[Integer, MText, ()] :-> '[MText, Integer, MText, ()]
_dupSample1 = forall a (st :: [*]). DupT st a st => st :-> (a : st)
dupT @MText
class DipT (origInp :: [Type]) (a :: Type)
(inp :: [Type]) (dipInp :: [Type])
(dipOut :: [Type]) (out :: [Type])
| inp a -> dipInp, dipOut inp a -> out where
dipTImpl :: (dipInp :-> dipOut) -> (inp :-> out)
instance ( TypeError (StackElemNotFound origSt a)
, dipInp ~ TypeError ('Text "Undefined type (see next error)")
, out ~ TypeError ('Text "Undefined type (see next error)")
) =>
DipT origSt a '[] dipInp dipOut out where
dipTImpl :: (dipInp :-> dipOut) -> '[] :-> out
dipTImpl = Text -> (dipInp :-> dipOut) -> '[] :-> out
forall a. HasCallStack => Text -> a
error Text
"impossible"
instance {-# OVERLAPPING #-}
( If (a `IsElem` st)
(TypeError (StackElemAmbiguous origSt a))
(() :: Constraint)
, dipInp ~ (a : st)
, dipOut ~ out
) =>
DipT origSt a (a : st) dipInp dipOut out where
dipTImpl :: (dipInp :-> dipOut) -> (a : st) :-> out
dipTImpl = (dipInp :-> dipOut) -> (a : st) :-> out
forall a. a -> a
id
instance {-# OVERLAPPABLE #-}
( DipT origSt a st dipInp dipOut out
, out1 ~ (b : out)
) =>
DipT origSt a (b : st) dipInp dipOut out1 where
dipTImpl :: (dipInp :-> dipOut) -> (b : st) :-> out1
dipTImpl = (st :-> out) -> (b : st) :-> (b : out)
forall a (s :: [*]) (s' :: [*]).
HasCallStack =>
(s :-> s') -> (a : s) :-> (a : s')
dip ((st :-> out) -> (b : st) :-> (b : out))
-> ((dipInp :-> dipOut) -> st :-> out)
-> (dipInp :-> dipOut)
-> (b : st) :-> (b : out)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (origInp :: [*]) a (inp :: [*]) (dipInp :: [*])
(dipOut :: [*]) (out :: [*]).
DipT origInp a inp dipInp dipOut out =>
(dipInp :-> dipOut) -> inp :-> out
dipTImpl @origSt @a @st
dipT
:: forall a inp dinp dout out.
DipT inp a inp dinp dout out
=> (dinp :-> dout) -> (inp :-> out)
dipT :: forall a (inp :: [*]) (dinp :: [*]) (dout :: [*]) (out :: [*]).
DipT inp a inp dinp dout out =>
(dinp :-> dout) -> inp :-> out
dipT = forall (origInp :: [*]) a (inp :: [*]) (dipInp :: [*])
(dipOut :: [*]) (out :: [*]).
DipT origInp a inp dipInp dipOut out =>
(dipInp :-> dipOut) -> inp :-> out
dipTImpl @inp @a @inp @dinp
_dipSample1
:: [Natural, ()]
:-> '[ByteString]
-> [Integer, Text, Natural, ()]
:-> [Integer, Text, ByteString]
_dipSample1 :: ('[Natural, ()] :-> '[ByteString])
-> '[Integer, Text, Natural, ()] :-> '[Integer, Text, ByteString]
_dipSample1 = forall a (inp :: [*]) (dinp :: [*]) (dout :: [*]) (out :: [*]).
DipT inp a inp dinp dout out =>
(dinp :-> dout) -> inp :-> out
dipT @Natural
dropT
:: forall a inp dinp dout out.
( DipT inp a inp dinp dout out
, dinp ~ (a ': dout)
)
=> inp :-> out
dropT :: forall a (inp :: [*]) (dinp :: [*]) (dout :: [*]) (out :: [*]).
(DipT inp a inp dinp dout out, dinp ~ (a : dout)) =>
inp :-> out
dropT = forall a (inp :: [*]) (dinp :: [*]) (dout :: [*]) (out :: [*]).
DipT inp a inp dinp dout out =>
(dinp :-> dout) -> inp :-> out
dipT @a (a : dout) :-> dout
forall a (s :: [*]). (a : s) :-> s
drop
_dropSample1 :: [Integer, (), Natural] :-> [Integer, Natural]
_dropSample1 :: '[Integer, (), Natural] :-> '[Integer, Natural]
_dropSample1 = forall a (inp :: [*]) (dinp :: [*]) (dout :: [*]) (out :: [*]).
(DipT inp a inp dinp dout out, dinp ~ (a : dout)) =>
inp :-> out
dropT @()