-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Toolkit for building proof automation systems
--
-- Please see the README on GitHub at
-- https://github.com/githubuser/refinery#readme
@package refinery
@version 0.4.0.0
-- | The datatype that drives both Rules and Tactics
--
-- If you just want to build tactics, you probably want to use
-- Tactic instead. However, if you need to get involved in the
-- core of the library, this is the place to start.
--
-- Module : Refinery.ProofState Copyright : (c) Reed Mullanix 2019
-- License : BSD-style Maintainer : reedmullanix@gmail.com
module Refinery.ProofState
-- | The core data type of the library. This represents a reified,
-- in-progress proof strategy for a particular goal.
--
-- NOTE: We need to split up the extract type into ext' and
-- ext, as we want to be functorial (and monadic) in
-- ext, but it shows up in both co and contravariant positions.
-- Splitting the type variable up into two solves this problem, at the
-- cost of looking ugly.
data ProofStateT ext' ext err s m goal
-- | Represents a subgoal, and a continuation that tells us what to do with
-- the resulting extract.
Subgoal :: goal -> (ext' -> ProofStateT ext' ext err s m goal) -> ProofStateT ext' ext err s m goal
-- | Run an effect.
Effect :: m (ProofStateT ext' ext err s m goal) -> ProofStateT ext' ext err s m goal
-- | Run a stateful computation. We don't want to use StateT here,
-- as it doesn't play nice with backtracking.
Stateful :: (s -> (s, ProofStateT ext' ext err s m goal)) -> ProofStateT ext' ext err s m goal
-- | Combine together the results of two ProofStates, preserving
-- the order that they were synthesized in.
Alt :: ProofStateT ext' ext err s m goal -> ProofStateT ext' ext err s m goal -> ProofStateT ext' ext err s m goal
-- | Similar to Alt, but will interleave the results, rather than
-- just appending them. This is useful if the first argument produces
-- potentially infinite results.
Interleave :: ProofStateT ext' ext err s m goal -> ProofStateT ext' ext err s m goal -> ProofStateT ext' ext err s m goal
-- | Commit runs the first proofstate, and only runs the second if
-- the first does not produce any successful results.
Commit :: ProofStateT ext' ext err s m goal -> ProofStateT ext' ext err s m goal -> ProofStateT ext' ext err s m goal
-- | Silent failure. Always causes a backtrack, unlike Failure.
Empty :: ProofStateT ext' ext err s m goal
-- | This does double duty, depending on whether or not the user calls
-- proofs or partialProofs. In the first case, we ignore
-- the continutation, backtrack, and return an error in the result of
-- proofs. In the second, we treat this as a sort of "unsolvable
-- subgoal", and call the continuation with a hole.
Failure :: err -> (ext' -> ProofStateT ext' ext err s m goal) -> ProofStateT ext' ext err s m goal
-- | An installed error handler. These allow us to add annotations to
-- errors, or run effects.
Handle :: ProofStateT ext' ext err s m goal -> (err -> m err) -> ProofStateT ext' ext err s m goal
-- | Represents a simple extract.
Axiom :: ext -> ProofStateT ext' ext err s m goal
-- | MonadExtract describes the effects required to generate named
-- holes. The meta type parameter here is a so called
-- "metavariable", which can be thought of as a name for a hole.
class (Monad m) => MonadExtract meta ext err s m | m -> ext, m -> err, ext -> meta
-- | Generates a named "hole" of type ext, which should represent
-- an incomplete extract.
hole :: MonadExtract meta ext err s m => StateT s m (meta, ext)
-- | Generates a named "hole" of type ext, which should represent
-- an incomplete extract.
hole :: (MonadExtract meta ext err s m, MonadTrans t, MonadExtract meta ext err s m1, m ~ t m1) => StateT s m (meta, ext)
-- | Generates an "unsolvable hole" of type err, which should
-- represent an incomplete extract that we have no hope of solving.
--
-- These will get generated when you generate partial extracts via
-- runPartialTacticT.
unsolvableHole :: MonadExtract meta ext err s m => err -> StateT s m (meta, ext)
-- | Generates an "unsolvable hole" of type err, which should
-- represent an incomplete extract that we have no hope of solving.
--
-- These will get generated when you generate partial extracts via
-- runPartialTacticT.
unsolvableHole :: (MonadExtract meta ext err s m, MonadTrans t, MonadExtract meta ext err s m1, m ~ t m1) => err -> StateT s m (meta, ext)
-- | Represents a single result of the execution of some tactic.
data Proof s meta goal ext
Proof :: ext -> s -> [(meta, goal)] -> Proof s meta goal ext
-- | The extract of the tactic.
[pf_extract] :: Proof s meta goal ext -> ext
-- | The state at the end of tactic execution.
[pf_state] :: Proof s meta goal ext -> s
-- | All the goals that were still unsolved by the end of tactic execution.
[pf_unsolvedGoals] :: Proof s meta goal ext -> [(meta, goal)]
-- | The result of executing partialProofs.
data PartialProof s err meta goal ext
-- | A so called "partial proof". These are proofs that encountered errors
-- during execution.
PartialProof :: ext -> s -> [(meta, goal)] -> [(meta, err)] -> PartialProof s err meta goal ext
-- | Interpret a ProofStateT into a list of (possibly incomplete)
-- extracts. This function will cause a proof to terminate when it
-- encounters a Failure, and will return a Left. If you
-- want to still recieve an extract even when you encounter a failure,
-- you should use partialProofs.
proofs :: forall ext err s m goal meta. MonadExtract meta ext err s m => s -> ProofStateT ext ext err s m goal -> m (Either [err] [Proof s meta goal ext])
-- | Interpret a ProofStateT into a list of (possibly incomplete)
-- extracts. This function will continue producing an extract when it
-- encounters a Failure, leaving a hole in the extract in it's
-- place. If you want the extraction to terminate when you encounter an
-- error, you should use proofs.
partialProofs :: forall meta ext err s m goal. MonadExtract meta ext err s m => s -> ProofStateT ext ext err s m goal -> m (Either [PartialProof s err meta goal ext] [Proof s meta goal ext])
-- | subgoals fs p will apply a list of functions producing a new
-- ProofStateT to each of the subgoals of p in order. If
-- the list of functions is longer than the number of subgoals, then the
-- extra functions are ignored. If the list of functions is shorter, then
-- we simply apply pure to all of the remaining subgoals.
subgoals :: Functor m => [jdg -> ProofStateT ext ext err s m jdg] -> ProofStateT ext ext err s m jdg -> ProofStateT ext ext err s m jdg
-- | mapExtract f g p allows yout to modify the extract type of a
-- ProofState. This witness the Profunctor instance of
-- ProofStateT, which we can't write without a newtype due to the
-- position of the type variables
mapExtract :: Functor m => (a -> ext') -> (ext -> b) -> ProofStateT ext' ext err s m jdg -> ProofStateT a b err s m jdg
-- | MetaSubst captures the notion of substituting metavariables of
-- type meta into an extract of type ext. Note that
-- these substitutions should most likely _not_ be capture avoiding.
class MetaSubst meta ext | ext -> meta
-- | substMeta meta e1 e2 will substitute all occurances of
-- meta in e2 with e1.
substMeta :: MetaSubst meta ext => meta -> ext -> ext -> ext
-- | DependentMetaSubst captures the notion of substituting
-- metavariables of type meta into judgements of type
-- jdg. This really only matters when you are dealing with
-- dependent types, specifically existentials. For instance, consider the
-- goal Σ (x : A) (B x) The type of the second goal we would produce here
-- _depends_ on the solution to the first goal, so we need to know how to
-- substitute holes in judgements in order to properly implement
-- resume.
class MetaSubst meta ext => DependentMetaSubst meta jdg ext
-- | dependentSubst meta e j will substitute all occurances of
-- meta in j with e. This method only really
-- makes sense if you have goals that depend on earlier extracts. If this
-- isn't the case, don't implement this.
dependentSubst :: DependentMetaSubst meta jdg ext => meta -> ext -> jdg -> jdg
-- | speculate s p will record the current state of the proof as
-- part of the extraction process. In doing so, this will also remove any
-- subgoal constructors by filling them with holes.
speculate :: forall meta ext err s m jdg x. MonadExtract meta ext err s m => s -> ProofStateT ext ext err s m jdg -> ProofStateT ext (Either err (Proof s meta jdg ext)) err s m x
instance GHC.Base.Functor m => GHC.Base.Functor (Refinery.ProofState.ProofStateT ext' ext err s m)
instance GHC.Generics.Generic (Refinery.ProofState.ProofStateT ext' ext err s m goal)
instance GHC.Generics.Generic (Refinery.ProofState.Proof s meta goal ext)
instance (GHC.Show.Show ext, GHC.Show.Show s, GHC.Show.Show meta, GHC.Show.Show goal) => GHC.Show.Show (Refinery.ProofState.Proof s meta goal ext)
instance (GHC.Classes.Eq ext, GHC.Classes.Eq s, GHC.Classes.Eq meta, GHC.Classes.Eq goal) => GHC.Classes.Eq (Refinery.ProofState.Proof s meta goal ext)
instance GHC.Generics.Generic (Refinery.ProofState.PartialProof s err meta goal ext)
instance (GHC.Show.Show ext, GHC.Show.Show s, GHC.Show.Show meta, GHC.Show.Show goal, GHC.Show.Show err) => GHC.Show.Show (Refinery.ProofState.PartialProof s err meta goal ext)
instance (GHC.Classes.Eq ext, GHC.Classes.Eq s, GHC.Classes.Eq meta, GHC.Classes.Eq goal, GHC.Classes.Eq err) => GHC.Classes.Eq (Refinery.ProofState.PartialProof s err meta goal ext)
instance Refinery.ProofState.MonadExtract meta ext err s m => Refinery.ProofState.MonadExtract meta ext err s (Control.Monad.Trans.Reader.ReaderT r m)
instance Refinery.ProofState.MonadExtract meta ext err s m => Refinery.ProofState.MonadExtract meta ext err s (Control.Monad.Trans.State.Lazy.StateT s m)
instance (Refinery.ProofState.MonadExtract meta ext err s m, GHC.Base.Monoid w) => Refinery.ProofState.MonadExtract meta ext err s (Control.Monad.Trans.Writer.Lazy.WriterT w m)
instance (Refinery.ProofState.MonadExtract meta ext err s m, GHC.Base.Monoid w) => Refinery.ProofState.MonadExtract meta ext err s (Control.Monad.Trans.Writer.Strict.WriterT w m)
instance Refinery.ProofState.MonadExtract meta ext err s m => Refinery.ProofState.MonadExtract meta ext err s (Control.Monad.Trans.Except.ExceptT err m)
instance (GHC.Show.Show goal, GHC.Show.Show err, GHC.Show.Show ext, GHC.Show.Show (m (Refinery.ProofState.ProofStateT ext' ext err s m goal))) => GHC.Show.Show (Refinery.ProofState.ProofStateT ext' ext err s m goal)
instance GHC.Base.Functor m => GHC.Base.Applicative (Refinery.ProofState.ProofStateT ext ext err s m)
instance Control.Monad.Morph.MFunctor (Refinery.ProofState.ProofStateT ext' ext err s)
instance GHC.Base.Functor m => GHC.Base.Monad (Refinery.ProofState.ProofStateT ext ext err s m)
instance Control.Monad.Trans.Class.MonadTrans (Refinery.ProofState.ProofStateT ext ext err s)
instance GHC.Base.Monad m => GHC.Base.Alternative (Refinery.ProofState.ProofStateT ext ext err s m)
instance GHC.Base.Monad m => GHC.Base.MonadPlus (Refinery.ProofState.ProofStateT ext ext err s m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Refinery.ProofState.ProofStateT ext ext err s m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Refinery.ProofState.ProofStateT ext ext err s m)
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState s (Refinery.ProofState.ProofStateT ext ext err s m)
-- |
WARNING
--
-- This module is considered internal, and can change at any given
-- time.
module Refinery.Tactic.Internal
-- | A TacticT is a monad transformer that performs proof
-- refinement. The type variables signifiy:
--
--
-- - jdg - The goal type. This is the thing we are trying to
-- construct a proof of.
-- - ext - The extract type. This is what we will recieve
-- after running the tactic.
-- - err - The error type. We can use throwError to
-- abort the computation with a provided error
-- - s - The state type.
-- - m - The base monad.
-- - a - The return value. This to make
-- TacticT a monad, and will always be
-- 'Prelude.()'
--
--
-- One of the most important things about this type is it's Monad
-- instance. t1 >> t2 Will execute t1 against the
-- current goal, and then execute t2 on _all_ of the subgoals
-- generated by t2.
--
-- This Monad instance is lawful, and has been tested thouroughly, and a
-- version of it has been formally verified in Agda. _However_, just
-- because it is correct doesn't mean that it lines up with your
-- intuitions of how Monads behave! In practice, it feels like a
-- combination of the Non-Determinisitic Monads and some of the Time
-- Travelling ones. That doesn't mean that it's impossible to understand,
-- just that it may push the boundaries of you intuitions.
newtype TacticT jdg ext err s m a
TacticT :: StateT jdg (ProofStateT ext ext err s m) a -> TacticT jdg ext err s m a
[unTacticT] :: TacticT jdg ext err s m a -> StateT jdg (ProofStateT ext ext err s m) a
-- | Helper function for producing a tactic.
tactic :: (jdg -> ProofStateT ext ext err s m (a, jdg)) -> TacticT jdg ext err s m a
-- | proofState t j will deconstruct a tactic t into a
-- ProofStateT by running it at j.
proofState :: TacticT jdg ext err s m a -> jdg -> ProofStateT ext ext err s m (a, jdg)
-- | Like proofState, but we discard the return value of t.
proofState_ :: Functor m => TacticT jdg ext err s m a -> jdg -> ProofStateT ext ext err s m jdg
-- | Map the unwrapped computation using the given function
mapTacticT :: Monad m => (m a -> m b) -> TacticT jdg ext err s m a -> TacticT jdg ext err s m b
-- | A RuleT is a monad transformer for creating inference
-- rules.
newtype RuleT jdg ext err s m a
RuleT :: ProofStateT ext a err s m jdg -> RuleT jdg ext err s m a
[unRuleT] :: RuleT jdg ext err s m a -> ProofStateT ext a err s m jdg
-- | Create a subgoal, and return the resulting extract.
subgoal :: jdg -> RuleT jdg ext err s m ext
-- | Create an "unsolvable" hole. These holes are ignored by subsequent
-- tactics, but do not cause a backtracking failure.
unsolvable :: err -> RuleT jdg ext err s m ext
instance GHC.Generics.Generic (Refinery.Tactic.Internal.TacticT jdg ext err s m a)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Refinery.Tactic.Internal.TacticT jdg ext err s m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Refinery.Tactic.Internal.TacticT jdg ext err s m)
instance GHC.Base.Monad m => GHC.Base.MonadPlus (Refinery.Tactic.Internal.TacticT jdg ext err s m)
instance GHC.Base.Functor m => GHC.Base.Monad (Refinery.Tactic.Internal.TacticT jdg ext err s m)
instance GHC.Base.Monad m => GHC.Base.Alternative (Refinery.Tactic.Internal.TacticT jdg ext err s m)
instance GHC.Base.Functor m => GHC.Base.Applicative (Refinery.Tactic.Internal.TacticT jdg ext err s m)
instance GHC.Base.Functor m => GHC.Base.Functor (Refinery.Tactic.Internal.TacticT jdg ext err s m)
instance GHC.Generics.Generic (Refinery.Tactic.Internal.RuleT jdg ext err s m a)
instance (GHC.Show.Show jdg, GHC.Show.Show err, GHC.Show.Show a, GHC.Show.Show (m (Refinery.ProofState.ProofStateT ext a err s m jdg))) => GHC.Show.Show (Refinery.Tactic.Internal.RuleT jdg ext err s m a)
instance GHC.Base.Functor m => GHC.Base.Functor (Refinery.Tactic.Internal.RuleT jdg ext err s m)
instance GHC.Base.Monad m => GHC.Base.Applicative (Refinery.Tactic.Internal.RuleT jdg ext err s m)
instance GHC.Base.Monad m => GHC.Base.Alternative (Refinery.Tactic.Internal.RuleT jdg ext err s m)
instance GHC.Base.Monad m => GHC.Base.Monad (Refinery.Tactic.Internal.RuleT jdg ext err s m)
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState s (Refinery.Tactic.Internal.RuleT jdg ext err s m)
instance Control.Monad.Trans.Class.MonadTrans (Refinery.Tactic.Internal.RuleT jdg ext err s)
instance Control.Monad.Morph.MFunctor (Refinery.Tactic.Internal.RuleT jdg ext err s)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Refinery.Tactic.Internal.RuleT jdg ext err s m)
instance (GHC.Base.Monoid jdg, GHC.Show.Show a, GHC.Show.Show jdg, GHC.Show.Show err, GHC.Show.Show ext, GHC.Show.Show (m (Refinery.ProofState.ProofStateT ext ext err s m (a, jdg)))) => GHC.Show.Show (Refinery.Tactic.Internal.TacticT jdg ext err s m a)
instance Control.Monad.Morph.MFunctor (Refinery.Tactic.Internal.TacticT jdg ext err s)
instance Control.Monad.Trans.Class.MonadTrans (Refinery.Tactic.Internal.TacticT jdg ext err s)
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState s (Refinery.Tactic.Internal.TacticT jdg ext err s m)
-- | Tactics and Tactic Combinators
--
-- This module contains everything you need to start defining tactics and
-- tactic combinators. Module : Refinery.Tactic Copyright : (c) Reed
-- Mullanix 2019 License : BSD-style Maintainer : reedmullanix@gmail.com
module Refinery.Tactic
-- | A TacticT is a monad transformer that performs proof
-- refinement. The type variables signifiy:
--
--
-- - jdg - The goal type. This is the thing we are trying to
-- construct a proof of.
-- - ext - The extract type. This is what we will recieve
-- after running the tactic.
-- - err - The error type. We can use throwError to
-- abort the computation with a provided error
-- - s - The state type.
-- - m - The base monad.
-- - a - The return value. This to make
-- TacticT a monad, and will always be
-- 'Prelude.()'
--
--
-- One of the most important things about this type is it's Monad
-- instance. t1 >> t2 Will execute t1 against the
-- current goal, and then execute t2 on _all_ of the subgoals
-- generated by t2.
--
-- This Monad instance is lawful, and has been tested thouroughly, and a
-- version of it has been formally verified in Agda. _However_, just
-- because it is correct doesn't mean that it lines up with your
-- intuitions of how Monads behave! In practice, it feels like a
-- combination of the Non-Determinisitic Monads and some of the Time
-- Travelling ones. That doesn't mean that it's impossible to understand,
-- just that it may push the boundaries of you intuitions.
data TacticT jdg ext err s m a
-- | Runs a tactic, producing a list of possible extracts, along with a
-- list of unsolved subgoals. Note that this function will backtrack on
-- errors. If you want a version that provides partial proofs, use
-- runPartialTacticT
runTacticT :: MonadExtract meta ext err s m => TacticT jdg ext err s m () -> jdg -> s -> m (Either [err] [Proof s meta jdg ext])
-- | Runs a tactic, producing a list of possible extracts, along with a
-- list of unsolved subgoals. Note that this function will produce a so
-- called "Partial Proof". This means that we no longer backtrack on
-- errors, but rather leave an unsolved hole, and continue synthesizing a
-- extract. If you want a version that backgracks on errors, see
-- runTacticT.
--
-- Note that this version is inherently slower than runTacticT, as
-- it needs to continue producing extracts.
runPartialTacticT :: MonadExtract meta ext err s m => TacticT jdg ext err s m () -> jdg -> s -> m (Either [PartialProof s err meta jdg ext] [Proof s meta jdg ext])
-- | Run a tactic, and get just the list of extracts, ignoring any other
-- information.
evalTacticT :: MonadExtract meta ext err s m => TacticT jdg ext err s m () -> jdg -> s -> m [ext]
-- | Represents a single result of the execution of some tactic.
data Proof s meta goal ext
Proof :: ext -> s -> [(meta, goal)] -> Proof s meta goal ext
-- | The extract of the tactic.
[pf_extract] :: Proof s meta goal ext -> ext
-- | The state at the end of tactic execution.
[pf_state] :: Proof s meta goal ext -> s
-- | All the goals that were still unsolved by the end of tactic execution.
[pf_unsolvedGoals] :: Proof s meta goal ext -> [(meta, goal)]
-- | The result of executing partialProofs.
data PartialProof s err meta goal ext
-- | A so called "partial proof". These are proofs that encountered errors
-- during execution.
PartialProof :: ext -> s -> [(meta, goal)] -> [(meta, err)] -> PartialProof s err meta goal ext
-- | Create a tactic that applies each of the tactics in the list to one
-- subgoal.
--
-- When the number of subgoals is greater than the number of provided
-- tactics, the identity tactic is applied to the remainder. When the
-- number of subgoals is less than the number of provided tactics, the
-- remaining tactics are ignored.
(<@>) :: Functor m => TacticT jdg ext err s m a -> [TacticT jdg ext err s m a] -> TacticT jdg ext err s m a
-- | t1 % t2 will interleave the execution of t1
-- and t2. This is useful if t1 will produce an
-- infinite number of extracts, as we will still run t2. This is
-- contrasted with t1 | t2, which will not ever consider
-- t2 if t1 produces an infinite number of extracts.
(<%>) :: TacticT jdg ext err s m a -> TacticT jdg ext err s m a -> TacticT jdg ext err s m a
infixr 3 <%>
-- | Tries to run a tactic, backtracking on failure
try :: Monad m => TacticT jdg ext err s m () -> TacticT jdg ext err s m ()
-- | commit t1 t2 will run t1, and then run t2
-- only if t1 (and all subsequent tactics) failed to produce any
-- successes.
--
-- NOTE: commit does have some sneaky semantics that you have to
-- be aware of. Specifically, it interacts a bit surprisingly with
-- >>=. Namely, the following algebraic law holds
-- commit t1 t2 >>= f = commit (t1 >>= f) (t2 >>= f)
-- For instance, if you have something like commit t1 t2
-- >>= somethingThatMayFail, then this law implies that this
-- is the same as commit (t1 >>= somethingThatMayFail) (t2
-- >>= somethingThatMayFail), which means that we might
-- execute t2 _even if_ t1 seemingly succeeds.
commit :: TacticT jdg ext err s m a -> TacticT jdg ext err s m a -> TacticT jdg ext err s m a
-- | Runs a tactic 0 or more times until it fails. Note that many_
-- is almost always the right choice over many. Due to the
-- semantics of Alternative, many will create a bunch of
-- partially solved goals along the way, one for each iteration.
many_ :: Monad m => TacticT jdg ext err s m () -> TacticT jdg ext err s m ()
-- | Runs a tactic 1 or more times until it fails. Note that some_
-- is almost always the right choice over some. Due to the
-- semantics of Alternative, some will create a bunch of
-- partially solved goals along the way, one for each iteration.
some_ :: Monad m => TacticT jdg ext err s m () -> TacticT jdg ext err s m ()
-- | choice ts will run all of the tactics in the list against the
-- current subgoals, and interleave their extracts in a manner similar to
-- <%>.
choice :: Monad m => [TacticT jdg ext err s m a] -> TacticT jdg ext err s m a
-- | progress eq err t applies the tactic t, and checks
-- to see if the resulting subgoals are all equal to the initial goal by
-- using eq. If they are, it throws err.
progress :: Monad m => (jdg -> jdg -> Bool) -> err -> TacticT jdg ext err s m a -> TacticT jdg ext err s m a
-- | ensure p f t runs the tactic t, and applies a
-- predicate to the state after the execution of t. We also run
-- a "cleanup" function f. Note that the predicate is applied to
-- the state _before_ the cleanup function is run.
ensure :: Monad m => (s -> Maybe err) -> (s -> s) -> TacticT jdg ext err s m () -> TacticT jdg ext err s m ()
-- | failure err will create an unsolvable hole that will be
-- ignored by subsequent tactics.
failure :: err -> TacticT jdg ext err s m a
-- | handler f will install an "error handler". These let you add
-- more context to errors, and potentially run effects. For instance, you
-- may want to take note that a particular situation is unsolvable, and
-- that we shouldn't attempt to run this series of tactics against a
-- given goal again.
--
-- Note that handlers further down the stack get run before those higher
-- up the stack. For instance, consider the following example:
-- handler f >> handler g >> failure err Here,
-- g will get run before f.
handler :: (err -> m err) -> TacticT jdg ext err s m ()
-- | A variant of handler that doesn't modify the error at all, and
-- solely exists to run effects.
handler_ :: Functor m => (err -> m ()) -> TacticT jdg ext err s m ()
-- | tweak f t lets us modify the extract produced by the tactic
-- t.
tweak :: Functor m => (ext -> ext) -> TacticT jdg ext err s m () -> TacticT jdg ext err s m ()
-- | Get the current goal
goal :: Functor m => TacticT jdg ext err s m jdg
-- | Inspect the current goal.
inspect :: Functor m => (jdg -> a) -> TacticT jdg ext err s m a
-- | Apply the first tactic, and then apply the second tactic focused on
-- the nth subgoal.
focus :: Functor m => TacticT jdg ext err s m () -> Int -> TacticT jdg ext err s m () -> TacticT jdg ext err s m ()
-- | MonadExtract describes the effects required to generate named
-- holes. The meta type parameter here is a so called
-- "metavariable", which can be thought of as a name for a hole.
class (Monad m) => MonadExtract meta ext err s m | m -> ext, m -> err, ext -> meta
-- | Generates a named "hole" of type ext, which should represent
-- an incomplete extract.
hole :: MonadExtract meta ext err s m => StateT s m (meta, ext)
-- | Generates a named "hole" of type ext, which should represent
-- an incomplete extract.
hole :: (MonadExtract meta ext err s m, MonadTrans t, MonadExtract meta ext err s m1, m ~ t m1) => StateT s m (meta, ext)
-- | Generates an "unsolvable hole" of type err, which should
-- represent an incomplete extract that we have no hope of solving.
--
-- These will get generated when you generate partial extracts via
-- runPartialTacticT.
unsolvableHole :: MonadExtract meta ext err s m => err -> StateT s m (meta, ext)
-- | Generates an "unsolvable hole" of type err, which should
-- represent an incomplete extract that we have no hope of solving.
--
-- These will get generated when you generate partial extracts via
-- runPartialTacticT.
unsolvableHole :: (MonadExtract meta ext err s m, MonadTrans t, MonadExtract meta ext err s m1, m ~ t m1) => err -> StateT s m (meta, ext)
-- | A RuleT is a monad transformer for creating inference
-- rules.
data RuleT jdg ext err s m a
-- | Turn an inference rule that examines the current goal into a tactic.
rule :: Monad m => (jdg -> RuleT jdg ext err s m ext) -> TacticT jdg ext err s m ()
-- | Turn an inference rule into a tactic.
rule_ :: Monad m => RuleT jdg ext err s m ext -> TacticT jdg ext err s m ()
-- | Create a subgoal, and return the resulting extract.
subgoal :: jdg -> RuleT jdg ext err s m ext
-- | Create an "unsolvable" hole. These holes are ignored by subsequent
-- tactics, but do not cause a backtracking failure.
unsolvable :: err -> RuleT jdg ext err s m ext
-- | MetaSubst captures the notion of substituting metavariables of
-- type meta into an extract of type ext. Note that
-- these substitutions should most likely _not_ be capture avoiding.
class MetaSubst meta ext | ext -> meta
-- | substMeta meta e1 e2 will substitute all occurances of
-- meta in e2 with e1.
substMeta :: MetaSubst meta ext => meta -> ext -> ext -> ext
-- | DependentMetaSubst captures the notion of substituting
-- metavariables of type meta into judgements of type
-- jdg. This really only matters when you are dealing with
-- dependent types, specifically existentials. For instance, consider the
-- goal Σ (x : A) (B x) The type of the second goal we would produce here
-- _depends_ on the solution to the first goal, so we need to know how to
-- substitute holes in judgements in order to properly implement
-- resume.
class MetaSubst meta ext => DependentMetaSubst meta jdg ext
-- | dependentSubst meta e j will substitute all occurances of
-- meta in j with e. This method only really
-- makes sense if you have goals that depend on earlier extracts. If this
-- isn't the case, don't implement this.
dependentSubst :: DependentMetaSubst meta jdg ext => meta -> ext -> jdg -> jdg
-- | reify t f will execute the tactic t, and resolve all
-- of it's subgoals by filling them with holes. The resulting subgoals
-- and partial extract are then passed to f.
reify :: forall meta jdg ext err s m. MonadExtract meta ext err s m => TacticT jdg ext err s m () -> (Proof s meta jdg ext -> TacticT jdg ext err s m ()) -> TacticT jdg ext err s m ()
-- | resume goals partial allows for resumption of execution after
-- a call to reify. If your language doesn't support dependent
-- subgoals, consider using resume' instead.
resume :: forall meta jdg ext err s m. (DependentMetaSubst meta jdg ext, Monad m) => Proof s meta jdg ext -> TacticT jdg ext err s m ()
-- | A version of resume that doesn't perform substitution into
-- the goal types. This only makes sense if your language doesn't support
-- dependent subgoals. If it does, use resume instead, as this
-- will leave the dependent subgoals with holes in them.
resume' :: forall meta jdg ext err s m. (MetaSubst meta ext, Monad m) => Proof s meta jdg ext -> TacticT jdg ext err s m ()
-- | pruning t p will execute t, and then apply
-- p to any subgoals it generates. If this predicate returns an
-- error, we terminate the execution. Otherwise, we resume execution via
-- resume'.
pruning :: (MetaSubst meta ext, MonadExtract meta ext err s m) => TacticT jdg ext err s m () -> ([jdg] -> Maybe err) -> TacticT jdg ext err s m ()
-- | peek t p will execute t, and then apply p
-- to the extract it produces. If this predicate returns an error, we
-- terminate the execution. Otherwise, we resume execution via
-- resume'.
--
-- Note that the extract produced may contain holes, as it is the extract
-- produced by running _just_ t against the current goal.
peek :: (MetaSubst meta ext, MonadExtract meta ext err s m) => TacticT jdg ext err s m () -> (ext -> Maybe err) -> TacticT jdg ext err s m ()
-- | attempt t1 t2 will partially execute t1, inspect
-- it's result, and only run t2 if it fails. If t1
-- succeeded, we will resume' execution of it.
attempt :: (MonadExtract meta ext err s m, MetaSubst meta ext) => TacticT jdg ext err s m () -> TacticT jdg ext err s m () -> TacticT jdg ext err s m ()