MK
Size: a a a
MK
MK
R
{- Note [Universes]
A universe is a collection of tags for types. It can be finite like
data U a where
UUnit :: U ()
UInt :: U Int
(where 'UUnit' is a tag for '()' and 'UInt' is a tag for 'Int') or infinite like
data U a where
UBool :: U Bool
UList :: !(U a) -> U [a]
Here are some values of the latter 'U' / the types that they encode
UBool / Bool
UList UBool / [Bool]
UList (UList UBool) / [[Bool]]
'U' being a GADT allows to package a type from a universe together with a value of that type.
For example,
Some (ValueOf UBool True) :: Some (ValueOf U)
We say that a type is in a universe whenever there is a tag for that type in the universe.
For example, 'Int' is in 'U', because there exists a tag for 'Int' in 'U' -- 'UInt'.
-}
-- | A value of a particular type from a universe.
data ValueOf uni a = ValueOf (uni a) a
-- | A universe is 'Closed', if it's known how to constrain every type from the universe.
-- The universe doesn't have to be finite
class Closed uni where
-- | A constrant for \"@constr a@ holds for any @a@ from @uni@\".
type Everywhere uni (constr :: GHC.Type -> Constraint) :: Constraint
-- | Bring a @constr a@ instance in scope, provided @a@ is a type from the universe and
-- @constr@ holds for any type from the universe.
bring :: uni `Everywhere` constr => proxy constr -> uni a -> (constr a => r) -> r
instance (Closed uni, uni `Everywhere` NFData) => NFData (ValueOf uni a) where
rnf (ValueOf uni x) = bring (Proxy @NFData) uni $ rnf x
MK
JS
к
MK
App x (App y (App z (....)
MK
BK
JS
JS
JS
JS