-- 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: -- -- -- -- 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: -- -- -- -- 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 ()