>{-# OPTIONS_GHC -fglasgow-exts #-}>-- | >-- Module : Ivor.Construction>-- Copyright : Edwin Brady>-- Licence : BSD-style (see LICENSE in the distribution)>-->-- Maintainer : eb@dcs.st-and.ac.uk>-- Stability : experimental>-- Portability : non-portable>-- >-- Some generic tactics for solving goals by applying constructors>moduleIvor.Construction(auto,split,left,right,useCon,exists,>isItJust)where>importIvor.TT>importDebug.Trace>-- | Tries to solve a simple goal automatically by trying each of these >-- in turn:>-- * Looking for an assumption ('trivial')>-- * 'intros' everything then solve by 'auto'>-- * Splitting the goal, then solving each subgoal by 'auto'>-- * If the goal is of a type with more than one constructor, try 'auto'>-- on each constructor in turn.>-- FIXME: not that this actually works yet.>auto::Int-- ^ Search depth>->Tactic>auto0=\gctxt->fail"auto got bored, try a bigger search depth">auton=\gctxt->if(allSolvedctxt)thenreturnctxtelse>trace("Auto "++shown)$>((trivial>+>(auton))>|>>(intros1>+>(auton))>|>>(split>+>(auton))>|>>(left>+>(auto(n-1)))>|>>(right>+>(auto(n-1))))gctxt>-- | Split a goal into subgoals. Type of goal must be a one constructor>-- family, with constructor @c@, then proceeds by 'refine' @c@.>split::Tactic>split=useCon10>-- | Split a goal into subgoals. Type of goal must be a two constructor>-- family, with constructors @l@ and @r@, then proceeds by 'refine' @l@.>left::Tactic>left=useCon20>-- | Split a goal into subgoals. Type of goal must be a two constructor>-- family, with constructors @l@ and @r@, then proceeds by 'refine' @r@.>right::Tactic>right=useCon21Getthegoal,lookatthetype.Refinebytheconstructorofthattype-checkthatthereistherightnumber(num).>-- | Solve the goal by applying a numbered constructor>useCon::Int-- ^ Ensure at least this number of constructors (0 for no constraint)>->Int-- ^ Use this constructor (0 based, order of definition)>->Tactic>useConnumusegctxt=do>goal<-goalDatactxtFalseg>letty=getApp(view(goalTypegoal))>casetyof>(Name_n)->docons<-getConstructorsctxtn>splitnConconsgctxt>_->fail"Not a type constructor">wheresplitnConcs|lengthcs>=num||num==0>=refine(NameDataCon(cs!!use))>splitnCon_=\gctxt->fail$"Not a "++shownum++" constructor family">-- | Solve an existential by providing a witness.>-- More generally; apply the first constructor of the >-- goal's type and provide the witness as its first non-inferrable argument.>exists::IsTerma=>a-- ^Witness >->Tactic>existst=useCon10>+>fillt>-- | Try to solve a goal @A@ by evaluating a term of type @Maybe A@. If the>-- answer is @Just a@, fill in the goal with the proof term @a@.>isItJust::IsTerma=>a->Tactic>isItJusttmgctxt=do>gd<-goalDatactxtFalseg>letgty=view$goalTypegd>vtm<-evalCtxtctxtgtm>let(prf,ty)=(viewvtm,viewTypevtm)>-- make sure type is 'Maybe'>casetyof>(App(Name_m)a)|m==(name"Maybe")>->docaseprfof>(App(Name_n)_)|n==(name"Nothing")>->fail"No solution found">(App(App(Name_j)_)p)|j==(name"Just")>->fillpgctxt>tm->fail$"Evaluated to "++showtm>_->fail$"Type of decision procedure must be ++ "++>show(App(NameUnknown(name"Maybe"))gty)