Safe Haskell | None |
---|---|
Language | Haskell2010 |
Check that a datatype is deeply strict, ie, it recursively only has strict fields.
Synopsis
- data DeepStrict reason
- = DeepStrict
- | NotDeepStrict !reason
- data DeepStrictReason
- type DeepStrictWithReason = DeepStrict [DeepStrictReason]
- isDeepStrict :: Type -> Q DeepStrictWithReason
- isDeepStrictWith :: Context -> Type -> Q DeepStrictWithReason
- assertDeepStrict :: Type -> Q [Dec]
- assertDeepStrictWith :: Context -> Type -> Q [Dec]
- data Context = Context {
- contextSpine :: !(Set Type)
- contextCache :: !(IORef (Map Type DeepStrictWithReason))
- contextOverride :: !(Map Name (Maybe [Strictness]))
- contextRecursionDepth :: !Int
- data Strictness
- emptyContext :: Q Context
- type FieldKey = Either Int Name
DeepStrict
data DeepStrict reason Source #
A type is deep strict if and only if for each constructor:
- All of its fields are strict, ie, they have a
!
if possible. - The type of of each field is deep strict.
The Monoid instance allows us to gather up reasons why a type fails to be deep strict.
Examples
()
is deep strict because its single constructor doesn't have any fields so it is vacuously deep strict.
Int
, Char
, etc are all deep strict because they are wrappers around unlifted types that cannot be lazy.
Maybe Int
is not deep strict.
It has a Nothing
constructor, which is fine.
But, the Just
constructor has a lazy field, which means it's not deep strict.
DeepStrict | |
NotDeepStrict !reason |
Instances
data DeepStrictReason Source #
Reasons why a type fails to be deep strict.
LazyType !Type ![DeepStrictReason] | The type is lazy. |
LazyConstructor !Name ![DeepStrictReason] | The type has a lazy constructor. |
FieldReason !FieldKey ![DeepStrictReason] | One of the fields of the constructor fails to be deep strict. |
LazyField !FieldKey | One of the fields of the constructor is lazy, ie, doesn't have a |
LazyOther !String |
Instances
Checking data types
isDeepStrict :: Type -> Q DeepStrictWithReason Source #
Determine if a type is deep strict
Invariant: The type doesn't contain any free variables, eg, Maybe a
will fail.
isDeepStrictWith :: Context -> Type -> Q DeepStrictWithReason Source #
assertDeepStrict :: Type -> Q [Dec] Source #
Assert that a type is deep strict. If the type isn't deep strict then this will produce an error with the reasons why.
Context
Allow overriding various setting that determine what types we consider deep strict.
Context | |
|
data Strictness Source #
Whether a type is used strictly by a data type.
We use these to annotate types with deep strictness overrides.
Types that have fields labelled as Strict
require those types to be deep strict.
Types that have fields labelled as Lazy
will never be deep strict, but this can be helpful for nicer messages.
Instances
Show Strictness Source # | |
Defined in Language.Haskell.TH.DeepStrict showsPrec :: Int -> Strictness -> ShowS # show :: Strictness -> String # showList :: [Strictness] -> ShowS # | |
Eq Strictness Source # | |
Defined in Language.Haskell.TH.DeepStrict (==) :: Strictness -> Strictness -> Bool # (/=) :: Strictness -> Strictness -> Bool # | |
Ord Strictness Source # | |
Defined in Language.Haskell.TH.DeepStrict compare :: Strictness -> Strictness -> Ordering # (<) :: Strictness -> Strictness -> Bool # (<=) :: Strictness -> Strictness -> Bool # (>) :: Strictness -> Strictness -> Bool # (>=) :: Strictness -> Strictness -> Bool # max :: Strictness -> Strictness -> Strictness # min :: Strictness -> Strictness -> Strictness # |