Agda-2.5.2: A dependently typed functional programming language and proof assistant

Safe Haskell | None
Language | Haskell2010

Agda.Termination.Monad

Contents

- Termination monad is a `MonadTCM`.
- Modifiers and accessors for the termination environment in the monad.
- De Bruijn patterns.
- Masked patterns (which are not eligible for structural descent, only for size descent)
- Call pathes
- Size depth estimation

Description

The monad for the termination checker.

The termination monad `TerM` is an extension of the type checking monad `TCM` by an environment with information needed by the termination checker.

Synopsis

- type MutualNames = [QName]
- type Target = QName
- type Guarded = Order
- data TerEnv = TerEnv {
  - terUseDotPatterns :: Bool
  - terGuardingTypeConstructors :: Bool
  - terInlineWithFunctions :: Bool
  - terSizeSuc :: Maybe QName
  - terSharp :: Maybe QName
  - terCutOff :: CutOff
  - terCurrent :: QName
  - terMutual :: MutualNames
  - terUserNames :: [QName]
  - terTarget :: Maybe Target
  - terDelayed :: Delayed
  - terMaskArgs :: [Bool]
  - terMaskResult :: Bool
  - _terSizeDepth :: Int
  - terPatterns :: MaskedDeBruijnPats
  - terPatternsRaise :: !Int
  - terGuarded :: !Guarded
  - terUseSizeLt :: Bool
  - terUsableVars :: VarSet
  }
- defaultTerEnv :: TerEnv
- class (Functor m, Monad m) => MonadTer m where
- newtype TerM a = TerM {
  - terM :: ReaderT TerEnv TCM a
  }
- runTer :: TerEnv -> TerM a -> TCM a
- runTerDefault :: TerM a -> TCM a
- terGetGuardingTypeConstructors :: TerM Bool
- terGetInlineWithFunctions :: TerM Bool
- terGetUseDotPatterns :: TerM Bool
- terSetUseDotPatterns :: Bool -> TerM a -> TerM a
- terGetSizeSuc :: TerM (Maybe QName)
- terGetCurrent :: TerM QName
- terSetCurrent :: QName -> TerM a -> TerM a
- terGetSharp :: TerM (Maybe QName)
- terGetCutOff :: TerM CutOff
- terGetMutual :: TerM MutualNames
- terGetUserNames :: TerM [QName]
- terGetTarget :: TerM (Maybe Target)
- terSetTarget :: Maybe Target -> TerM a -> TerM a
- terGetDelayed :: TerM Delayed
- terSetDelayed :: Delayed -> TerM a -> TerM a
- terGetMaskArgs :: TerM [Bool]
- terSetMaskArgs :: [Bool] -> TerM a -> TerM a
- terGetMaskResult :: TerM Bool
- terSetMaskResult :: Bool -> TerM a -> TerM a
- terGetPatterns :: TerM MaskedDeBruijnPats
- terSetPatterns :: MaskedDeBruijnPats -> TerM a -> TerM a
- terRaise :: TerM a -> TerM a
- terGetGuarded :: TerM Guarded
- terModifyGuarded :: (Order -> Order) -> TerM a -> TerM a
- terSetGuarded :: Order -> TerM a -> TerM a
- terUnguarded :: TerM a -> TerM a
- terPiGuarded :: TerM a -> TerM a
- terSizeDepth :: Lens' Int TerEnv
- terGetUsableVars :: TerM VarSet
- terModifyUsableVars :: (VarSet -> VarSet) -> TerM a -> TerM a
- terSetUsableVars :: VarSet -> TerM a -> TerM a
- terGetUseSizeLt :: TerM Bool
- terModifyUseSizeLt :: (Bool -> Bool) -> TerM a -> TerM a
- terSetUseSizeLt :: Bool -> TerM a -> TerM a
- withUsableVars :: UsableSizeVars a => a -> TerM b -> TerM b
- conUseSizeLt :: QName -> TerM a -> TerM a
- projUseSizeLt :: QName -> TerM a -> TerM a
- isProjectionButNotCoinductive :: MonadTCM tcm => QName -> tcm Bool
- isCoinductiveProjection :: MonadTCM tcm => Bool -> QName -> tcm Bool
- type DeBruijnPats = [DeBruijnPat]
- type DeBruijnPat = DeBruijnPat' Int
- data DeBruijnPat' a
  - = VarDBP a
  - | ConDBP QName [DeBruijnPat' a]
  - | LitDBP Literal
  - | TermDBP Term
  - | ProjDBP ProjOrigin QName
- patternDepth :: DeBruijnPat' a -> Int
- unusedVar :: DeBruijnPat
- raiseDBP :: Int -> DeBruijnPats -> DeBruijnPats
- class UsableSizeVars a where
- type MaskedDeBruijnPats = [Masked DeBruijnPat]
- data Masked a = Masked {
  - getMask :: Bool
  - getMasked :: a
  }
- masked :: a -> Masked a
- notMasked :: a -> Masked a
- newtype CallPath = CallPath {
  - callInfos :: [CallInfo]
  }
- terSetSizeDepth :: Telescope -> TerM a -> TerM a

# Documentation

type MutualNames = [QName] #

The mutual block we are checking.

The functions are numbered according to their order of appearance in this list.

type Target = QName #

The target of the function we are checking.

type Guarded = Order #

The current guardedness level.

data TerEnv #

The termination environment.

Constructors

TerEnv |
Fields terUseDotPatterns :: Bool Are we mining dot patterns to find evindence of structal descent? terGuardingTypeConstructors :: Bool Do we assume that record and data type constructors preserve guardedness? terInlineWithFunctions :: Bool Do we inline with functions to enhance termination checking of with? terSizeSuc :: Maybe QName The name of size successor, if any. terSharp :: Maybe QName The name of the delay constructor (sharp), if any. terCutOff :: CutOff Depth at which to cut off the structural order. terCurrent :: QName The name of the function we are currently checking. terMutual :: MutualNames The names of the functions in the mutual block we are checking. This includes the internally generated functions (with, extendedlambda, coinduction). terUserNames :: [QName] The list of name actually appearing in the file (abstract syntax). Excludes the internally generated functions. terTarget :: Maybe Target Target type of the function we are currently termination checking. Only the constructors of `Target` are considered guarding. terDelayed :: Delayed Are we checking a delayed definition? terMaskArgs :: [Bool] Only consider the `notMasked` `False` arguments for establishing termination. See issue #1023. terMaskResult :: Bool Only consider guardedness if `False` (not masked). _terSizeDepth :: Int How many `SIZELT` relations do we have in the context (= clause telescope). Used to approximate termination for metas in call args. terPatterns :: MaskedDeBruijnPats The patterns of the clause we are checking. terPatternsRaise :: !Int Number of additional binders we have gone under (and consequently need to raise the patterns to compare to terms). Updated during call graph extraction, hence strict. terGuarded :: !Guarded The current guardedness status. Changes as we go deeper into the term. Updated during call graph extraction, hence strict. terUseSizeLt :: Bool When extracting usable size variables during construction of the call matrix, can we take the variable for use with SIZELT constraints from the context? Yes, if we are under an inductive constructor. No, if we are under a record constructor. (See issue #1015). terUsableVars :: VarSet Pattern variables that can be compared to argument variables using SIZELT.

defaultTerEnv :: TerEnv #

An empty termination environment.

Values are set to a safe default meaning that with these initial values the termination checker will not miss termination errors it would have seen with better settings of these values.

Values that do not have a safe default are set to `IMPOSSIBLE`.

class (Functor m, Monad m) => MonadTer m where #

Termination monad service class.

Minimal complete definition

terAsk, terLocal

Methods

terAsk :: m TerEnv #

terLocal :: (TerEnv -> TerEnv) -> m a -> m a #

terAsks :: (TerEnv -> a) -> m a #

Instances

MonadTer TerM # |
Methods terAsk :: TerM TerEnv # terLocal :: (TerEnv -> TerEnv) -> TerM a -> TerM a # terAsks :: (TerEnv -> a) -> TerM a #

newtype TerM a #

Termination monad.

Constructors

TerM |
Fields terM :: ReaderT TerEnv TCM a

Instances

Monad TerM # |
Methods (>>=) :: TerM a -> (a -> TerM b) -> TerM b # (>>) :: TerM a -> TerM b -> TerM b # return :: a -> TerM a # fail :: String -> TerM a #
Functor TerM # |
Methods fmap :: (a -> b) -> TerM a -> TerM b # (<$) :: a -> TerM b -> TerM a #
Applicative TerM # |
Methods pure :: a -> TerM a # (<*>) :: TerM (a -> b) -> TerM a -> TerM b # (*>) :: TerM a -> TerM b -> TerM b # (<*) :: TerM a -> TerM b -> TerM a #
MonadIO TerM # |
Methods liftIO :: IO a -> TerM a #
MonadTCM TerM # |
Methods liftTCM :: TCM a -> TerM a #
HasConstInfo TerM # |
Methods getConstInfo :: QName -> TerM Definition # getRewriteRulesFor :: QName -> TerM RewriteRules #
MonadTer TerM # |
Methods terAsk :: TerM TerEnv # terLocal :: (TerEnv -> TerEnv) -> TerM a -> TerM a # terAsks :: (TerEnv -> a) -> TerM a #
MonadError TCErr TerM # |
Methods throwError :: TCErr -> TerM a # catchError :: TerM a -> (TCErr -> TerM a) -> TerM a #
MonadReader TCEnv TerM # |
Methods ask :: TerM TCEnv # local :: (TCEnv -> TCEnv) -> TerM a -> TerM a # reader :: (TCEnv -> a) -> TerM a #
MonadState TCState TerM # |
Methods get :: TerM TCState # put :: TCState -> TerM () # state :: (TCState -> (a, TCState)) -> TerM a #
MonadBench Phase TerM # |
Methods getBenchmark :: TerM (Benchmark Phase) # getsBenchmark :: (Benchmark Phase -> c) -> TerM c # putBenchmark :: Benchmark Phase -> TerM () # modifyBenchmark :: (Benchmark Phase -> Benchmark Phase) -> TerM () # finally :: TerM b -> TerM c -> TerM b #

runTer :: TerEnv -> TerM a -> TCM a #

Generic run method for termination monad.

runTerDefault :: TerM a -> TCM a #

Run TerM computation in default environment (created from options).

# Termination monad is a `MonadTCM`.

# Modifiers and accessors for the termination environment in the monad.

terGetGuardingTypeConstructors :: TerM Bool #

terGetInlineWithFunctions :: TerM Bool #

terGetUseDotPatterns :: TerM Bool #

terSetUseDotPatterns :: Bool -> TerM a -> TerM a #

terGetSizeSuc :: TerM (Maybe QName) #

terGetCurrent :: TerM QName #

terSetCurrent :: QName -> TerM a -> TerM a #

terGetSharp :: TerM (Maybe QName) #

terGetCutOff :: TerM CutOff #

terGetMutual :: TerM MutualNames #

terGetUserNames :: TerM [QName] #

terGetTarget :: TerM (Maybe Target) #

terSetTarget :: Maybe Target -> TerM a -> TerM a #

terGetDelayed :: TerM Delayed #

terSetDelayed :: Delayed -> TerM a -> TerM a #

terGetMaskArgs :: TerM [Bool] #

terSetMaskArgs :: [Bool] -> TerM a -> TerM a #

terGetMaskResult :: TerM Bool #

terSetMaskResult :: Bool -> TerM a -> TerM a #

terGetPatterns :: TerM MaskedDeBruijnPats #

terSetPatterns :: MaskedDeBruijnPats -> TerM a -> TerM a #

terRaise :: TerM a -> TerM a #

terGetGuarded :: TerM Guarded #

terModifyGuarded :: (Order -> Order) -> TerM a -> TerM a #

terSetGuarded :: Order -> TerM a -> TerM a #

terUnguarded :: TerM a -> TerM a #

terPiGuarded :: TerM a -> TerM a #

Should the codomain part of a function type preserve guardedness?

terSizeDepth :: Lens' Int TerEnv #

Lens for `_terSizeDepth`.

terGetUsableVars :: TerM VarSet #

Lens for `terUsableVars`.

terModifyUsableVars :: (VarSet -> VarSet) -> TerM a -> TerM a #

terSetUsableVars :: VarSet -> TerM a -> TerM a #

terGetUseSizeLt :: TerM Bool #

Lens for `terUseSizeLt`.

terModifyUseSizeLt :: (Bool -> Bool) -> TerM a -> TerM a #

terSetUseSizeLt :: Bool -> TerM a -> TerM a #

withUsableVars :: UsableSizeVars a => a -> TerM b -> TerM b #

Compute usable vars from patterns and run subcomputation.

conUseSizeLt :: QName -> TerM a -> TerM a #

Set `terUseSizeLt` when going under constructor `c`.

projUseSizeLt :: QName -> TerM a -> TerM a #

Set `terUseSizeLt` for arguments following projection `q`. We disregard j<i after a non-coinductive projection. However, the projection need not be recursive (Issue 1470).

isProjectionButNotCoinductive :: MonadTCM tcm => QName -> tcm Bool #

For termination checking purposes flat should not be considered a projection. That is, it flat doesn't preserve either structural order or guardedness like other projections do. Andreas, 2012-06-09: the same applies to projections of recursive records.

isCoinductiveProjection :: MonadTCM tcm => Bool -> QName -> tcm Bool #

Check whether a projection belongs to a coinductive record and is actually recursive. E.g. @ isCoinductiveProjection (Stream.head) = return False

isCoinductiveProjection (Stream.tail) = return True @

# De Bruijn patterns.

type DeBruijnPats = [DeBruijnPat] #

type DeBruijnPat = DeBruijnPat' Int #

Patterns with variables as de Bruijn indices.

data DeBruijnPat' a #

Constructors

VarDBP a | De Bruijn Index.
ConDBP QName [DeBruijnPat' a] | The name refers to either an ordinary constructor or the successor function on sized types.
LitDBP Literal | Literal. Also abused to censor part of a pattern.
TermDBP Term | Part of dot pattern that cannot be converted into a pattern.
ProjDBP ProjOrigin QName | Projection pattern.

Instances

Functor DeBruijnPat' # |
Methods fmap :: (a -> b) -> DeBruijnPat' a -> DeBruijnPat' b # (<$) :: a -> DeBruijnPat' b -> DeBruijnPat' a #
PrettyTCM DeBruijnPat # |
Methods prettyTCM :: DeBruijnPat -> TCM Doc #
UsableSizeVars MaskedDeBruijnPats # |
Methods usableSizeVars :: MaskedDeBruijnPats -> TerM VarSet #
UsableSizeVars DeBruijnPat # |
Methods usableSizeVars :: DeBruijnPat -> TerM VarSet #
UsableSizeVars DeBruijnPats # |
Methods usableSizeVars :: DeBruijnPats -> TerM VarSet #
Show a => Show (DeBruijnPat' a) # |
Methods showsPrec :: Int -> DeBruijnPat' a -> ShowS # show :: DeBruijnPat' a -> String # showList :: [DeBruijnPat' a] -> ShowS #
IsProjP (DeBruijnPat' a) # |
Methods isProjP :: DeBruijnPat' a -> Maybe (ProjOrigin, AmbiguousQName) #
UsableSizeVars (Masked DeBruijnPat) # |
Methods usableSizeVars :: Masked DeBruijnPat -> TerM VarSet #

patternDepth :: DeBruijnPat' a -> Int #

How long is the path to the deepest variable?

unusedVar :: DeBruijnPat #

A dummy pattern used to mask a pattern that cannot be used for structural descent.

raiseDBP :: Int -> DeBruijnPats -> DeBruijnPats #

`raiseDBP n ps` increases each de Bruijn index in `ps` by `n`. Needed when going under a binder during analysis of a term.

class UsableSizeVars a where #

Extract variables from `DeBruijnPat`s that could witness a decrease via a SIZELT constraint.

These variables must be under an inductive constructor (with no record constructor in the way), or after a coinductive projection (with no inductive one in the way).

Minimal complete definition

usableSizeVars

Methods

usableSizeVars :: a -> TerM VarSet #

Instances

UsableSizeVars MaskedDeBruijnPats # |
Methods usableSizeVars :: MaskedDeBruijnPats -> TerM VarSet #
UsableSizeVars DeBruijnPat # |
Methods usableSizeVars :: DeBruijnPat -> TerM VarSet #
UsableSizeVars DeBruijnPats # |
Methods usableSizeVars :: DeBruijnPats -> TerM VarSet #
UsableSizeVars (Masked DeBruijnPat) # |
Methods usableSizeVars :: Masked DeBruijnPat -> TerM VarSet #

# Masked patterns (which are not eligible for structural descent, only for size descent)

type MaskedDeBruijnPats = [Masked DeBruijnPat] #

data Masked a #

Constructors

Masked |
Fields getMask :: Bool True if thing not eligible for structural descent. getMasked :: a Thing.

Instances

Functor Masked # |
Methods fmap :: (a -> b) -> Masked a -> Masked b # (<$) :: a -> Masked b -> Masked a #
Foldable Masked # |
Methods fold :: Monoid m => Masked m -> m # foldMap :: Monoid m => (a -> m) -> Masked a -> m # foldr :: (a -> b -> b) -> b -> Masked a -> b # foldr' :: (a -> b -> b) -> b -> Masked a -> b # foldl :: (b -> a -> b) -> b -> Masked a -> b # foldl' :: (b -> a -> b) -> b -> Masked a -> b # foldr1 :: (a -> a -> a) -> Masked a -> a # foldl1 :: (a -> a -> a) -> Masked a -> a # toList :: Masked a -> [a] # null :: Masked a -> Bool # length :: Masked a -> Int # elem :: Eq a => a -> Masked a -> Bool # maximum :: Ord a => Masked a -> a # minimum :: Ord a => Masked a -> a # sum :: Num a => Masked a -> a # product :: Num a => Masked a -> a #
Traversable Masked # |
Methods traverse :: Applicative f => (a -> f b) -> Masked a -> f (Masked b) # sequenceA :: Applicative f => Masked (f a) -> f (Masked a) # mapM :: Monad m => (a -> m b) -> Masked a -> m (Masked b) # sequence :: Monad m => Masked (m a) -> m (Masked a) #
Decoration Masked # |
Methods traverseF :: Functor m => (a -> m b) -> Masked a -> m (Masked b) # distributeF :: Functor m => Masked (m a) -> m (Masked a) #
UsableSizeVars MaskedDeBruijnPats # |
Methods usableSizeVars :: MaskedDeBruijnPats -> TerM VarSet #
Eq a => Eq (Masked a) # |
Methods (==) :: Masked a -> Masked a -> Bool # (/=) :: Masked a -> Masked a -> Bool #
Ord a => Ord (Masked a) # |
Methods compare :: Masked a -> Masked a -> Ordering # (<) :: Masked a -> Masked a -> Bool # (<=) :: Masked a -> Masked a -> Bool # (>) :: Masked a -> Masked a -> Bool # (>=) :: Masked a -> Masked a -> Bool # max :: Masked a -> Masked a -> Masked a # min :: Masked a -> Masked a -> Masked a #
Show a => Show (Masked a) # |
Methods showsPrec :: Int -> Masked a -> ShowS # show :: Masked a -> String # showList :: [Masked a] -> ShowS #
PrettyTCM a => PrettyTCM (Masked a) # | Print masked things in double parentheses.
Methods prettyTCM :: Masked a -> TCM Doc #
UsableSizeVars (Masked DeBruijnPat) # |
Methods usableSizeVars :: Masked DeBruijnPat -> TerM VarSet #

masked :: a -> Masked a #

notMasked :: a -> Masked a #

# Call pathes

newtype CallPath #

The call information is stored as free monoid over `CallInfo`. As long as we never look at it, only accumulate it, it does not matter whether we use `Set`, (nub) list, or `Tree`. Internally, due to lazyness, it is anyway a binary tree of `mappend` nodes and singleton leafs. Since we define no order on `CallInfo` (expensive), we cannot use a `Set` or nub list. Performance-wise, I could not see a difference between Set and list.

Constructors

CallPath |
Fields callInfos :: [CallInfo]

Instances

Show CallPath # |
Methods showsPrec :: Int -> CallPath -> ShowS # show :: CallPath -> String # showList :: [CallPath] -> ShowS #
Semigroup CallPath # |
Methods (<>) :: CallPath -> CallPath -> CallPath # sconcat :: NonEmpty CallPath -> CallPath # stimes :: Integral b => b -> CallPath -> CallPath #
Monoid CallPath # |
Methods mempty :: CallPath # mappend :: CallPath -> CallPath -> CallPath # mconcat :: [CallPath] -> CallPath #
Pretty CallPath # | Only show intermediate nodes. (Drop last `CallInfo`).
Methods pretty :: CallPath -> Doc # prettyPrec :: Int -> CallPath -> Doc #
AllNames CallPath # |
Methods allNames :: CallPath -> Seq QName #

# Size depth estimation

terSetSizeDepth :: Telescope -> TerM a -> TerM a #

A very crude way of estimating the `SIZELT` chains `i > j > k` in context. Returns 3 in this case. Overapproximates.