linear-base-0.2.0: src/Data/Unrestricted/Linear/Internal/Ur.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE StandaloneDeriving #-}
-- for GHC.Types
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_HADDOCK hide #-}
module Data.Unrestricted.Linear.Internal.Ur
( Ur (..),
unur,
lift,
lift2,
)
where
import qualified GHC.Generics as GHCGen
import GHC.Types (Multiplicity (..))
import Generics.Linear
import Prelude.Linear.GenericUtil
import qualified Prelude
-- | @Ur a@ represents unrestricted values of type @a@ in a linear
-- context. The key idea is that because the contructor holds @a@ with a
-- regular arrow, a function that uses @Ur a@ linearly can use @a@
-- however it likes.
--
-- > someLinear :: Ur a %1-> (a,a)
-- > someLinear (Ur a) = (a,a)
data Ur a where
Ur :: a -> Ur a
deriving instance GHCGen.Generic (Ur a)
deriving instance GHCGen.Generic1 Ur
-- | Get an @a@ out of an @Ur a@. If you call this function on a
-- linearly bound @Ur a@, then the @a@ you get out has to be used
-- linearly, for example:
--
-- > restricted :: Ur a %1-> b
-- > restricted x = f (unur x)
-- > where
-- > -- f __must__ be linear
-- > f :: a %1-> b
-- > f x = ...
unur :: Ur a %1 -> a
unur (Ur a) = a
-- | Lifts a function on a linear @Ur a@.
lift :: (a -> b) -> Ur a %1 -> Ur b
lift f (Ur a) = Ur (f a)
-- | Lifts a function to work on two linear @Ur a@.
lift2 :: (a -> b -> c) -> Ur a %1 -> Ur b %1 -> Ur c
lift2 f (Ur a) (Ur b) = Ur (f a b)
instance Prelude.Functor Ur where
fmap f (Ur a) = Ur (f a)
instance Prelude.Foldable Ur where
foldMap f (Ur x) = f x
instance Prelude.Traversable Ur where
sequenceA (Ur x) = Prelude.fmap Ur x
instance Prelude.Applicative Ur where
pure = Ur
Ur f <*> Ur x = Ur (f x)
instance Prelude.Monad Ur where
Ur a >>= f = f a
-- -------------------
-- Generic and Generic1 instances
instance Generic (Ur a) where
type
Rep (Ur a) =
FixupMetaData
(Ur a)
( D1
Any
( C1
Any
( S1
Any
(MP1 'Many (Rec0 a))
)
)
)
to rur = to' rur
where
to' :: Rep (Ur a) p %1 -> Ur a
to' (M1 (M1 (M1 (MP1 (K1 a))))) = Ur a
from ur = from' ur
where
from' :: Ur a %1 -> Rep (Ur a) p
from' (Ur a) = M1 (M1 (M1 (MP1 (K1 a))))
instance Generic1 Ur where
type
Rep1 Ur =
FixupMetaData1
Ur
( D1
Any
( C1
Any
( S1
Any
(MP1 'Many Par1)
)
)
)
to1 rur = to1' rur
where
to1' :: Rep1 Ur a %1 -> Ur a
to1' (M1 (M1 (M1 (MP1 (Par1 a))))) = Ur a
from1 ur = from1' ur
where
from1' :: Ur a %1 -> Rep1 Ur a
from1' (Ur a) = M1 (M1 (M1 (MP1 (Par1 a))))
type family Any :: Meta