{-# LANGUAGE CPP #-}#if __GLASGOW_HASKELL__ >= 702 {-# LANGUAGE Safe #-}#endif #if __GLASGOW_HASKELL__ >= 706 {-# LANGUAGE PolyKinds #-}#endif #if __GLASGOW_HASKELL__ >= 710 {-# LANGUAGE AutoDeriveTypeable #-}#endif ------------------------------------------------------------------------------- |-- Module : Control.Monad.Trans.Select-- Copyright : (c) Ross Paterson 2017-- License : BSD-style (see the file LICENSE)---- Maintainer : R.Paterson@city.ac.uk-- Stability : experimental-- Portability : portable---- Selection monad transformer, modelling search algorithms.---- * Martin Escardo and Paulo Oliva.-- "Selection functions, bar recursion and backward induction",-- /Mathematical Structures in Computer Science/ 20:2 (2010), pp. 127-168.-- <https://www.cs.bham.ac.uk/~mhe/papers/selection-escardo-oliva.pdf>---- * Jules Hedges. "Monad transformers for backtracking search".-- In /Proceedings of MSFP 2014/. <https://arxiv.org/abs/1406.2058>-----------------------------------------------------------------------------moduleControl.Monad.Trans.Select(-- * The Select monadSelect ,select ,runSelect ,mapSelect ,-- * The SelectT monad transformerSelectT (SelectT ),runSelectT ,mapSelectT ,-- * Monad transformationselectToContT ,selectToCont ,)whereimportControl.Monad.IO.ClassimportControl.Monad.Trans.Class importControl.Monad.Trans.Cont importControl.ApplicativeimportControl.Monad#if MIN_VERSION_base(4,9,0) importqualifiedControl.Monad.FailasFail#endif importData.Functor.Identity-- | Selection monad.typeSelect r =SelectT r Identity-- | Constructor for computations in the selection monad.select::((a ->r )->a )->Select r a select f =SelectT $\k ->Identity(f (runIdentity.k )){-# INLINEselect#-}-- | Runs a @Select@ computation with a function for evaluating answers-- to select a particular answer. (The inverse of 'select'.)runSelect::Select r a ->(a ->r )->a runSelect m k =runIdentity(runSelectT m (Identity.k )){-# INLINErunSelect#-}-- | Apply a function to transform the result of a selection computation.---- * @'runSelect' ('mapSelect' f m) = f . 'runSelect' m@mapSelect::(a ->a )->Select r a ->Select r a mapSelect f =mapSelectT (Identity.f .runIdentity){-# INLINEmapSelect#-}-- | Selection monad transformer.---- 'SelectT' is not a functor on the category of monads, and many operations-- cannot be lifted through it.newtypeSelectT r m a =SelectT ((a ->m r )->m a )-- | Runs a @SelectT@ computation with a function for evaluating answers-- to select a particular answer. (The inverse of 'select'.)runSelectT::SelectT r m a ->(a ->m r )->m a runSelectT (SelectT g )=g {-# INLINErunSelectT#-}-- | Apply a function to transform the result of a selection computation.-- This has a more restricted type than the @map@ operations for other-- monad transformers, because 'SelectT' does not define a functor in-- the category of monads.---- * @'runSelectT' ('mapSelectT' f m) = f . 'runSelectT' m@mapSelectT::(m a ->m a )->SelectT r m a ->SelectT r m a mapSelectT f m =SelectT $f .runSelectT m {-# INLINEmapSelectT#-}instance(Functorm )=>Functor(SelectT r m )wherefmap f (SelectT g )=SelectT (fmapf .g .(.f )){-# INLINEfmap#-}instance(Functorm ,Monadm )=>Applicative(SelectT r m )wherepure =lift .return{-# INLINEpure#-}SelectT gf <*> SelectT gx =SelectT $\k ->doleth f =liftMf (gx (k .f ))f <-gf ((>>=k ).h )h f {-# INLINE(<*>)#-}m *> k =m >>=\_->k {-# INLINE(*>)#-}instance(Functorm ,MonadPlusm )=>Alternative(SelectT r m )whereempty =mzero{-# INLINEempty#-}(<|> )=mplus{-# INLINE(<|>)#-}instance(Monadm )=>Monad(SelectT r m )where#if !(MIN_VERSION_base(4,8,0)) return=lift.return{-# INLINEreturn#-}#endif SelectT g >>= f =SelectT $\k ->doleth x =runSelectT (f x )k y <-g ((>>=k ).h )h y {-# INLINE(>>=)#-}#if MIN_VERSION_base(4,9,0) instance(Fail.MonadFailm )=>Fail.MonadFail(SelectT r m )wherefail msg =lift (Fail.failmsg ){-# INLINEfail#-}#endif instance(MonadPlusm )=>MonadPlus(SelectT r m )wheremzero =SelectT (constmzero){-# INLINEmzero#-}SelectT f `mplus `SelectT g =SelectT $\k ->f k `mplus`g k {-# INLINEmplus#-}instanceMonadTrans (SelectT r )wherelift =SelectT .const{-# INLINElift#-}instance(MonadIOm )=>MonadIO(SelectT r m )whereliftIO =lift .liftIO{-# INLINEliftIO#-}-- | Convert a selection computation to a continuation-passing computation.selectToContT::(Monadm )=>SelectT r m a ->ContT r m a selectToContT (SelectT g )=ContT $\k ->g k >>=k {-# INLINEselectToCont#-}-- | Deprecated name for 'selectToContT'.{-# DEPRECATEDselectToCont"Use selectToContT instead"#-}selectToCont::(Monadm )=>SelectT r m a ->ContT r m a selectToCont =selectToContT