{-# LANGUAGE ExistentialQuantification, StandaloneDeriving, ScopedTypeVariables #-}
module OAlg.Control.Solver
(
Solver(), failure, handle, solve, solvable
)
where
import Control.Exception hiding (handle)
data Solver x
= Solution x
| forall e . Exception e => Failure e
deriving instance Show x => Show (Solver x)
instance Functor Solver where
fmap :: forall a b. (a -> b) -> Solver a -> Solver b
fmap a -> b
f (Solution a
x) = b -> Solver b
forall x. x -> Solver x
Solution (a -> b
f a
x)
fmap a -> b
_ (Failure e
e) = e -> Solver b
forall x e. Exception e => e -> Solver x
Failure e
e
instance Applicative Solver where
pure :: forall x. x -> Solver x
pure = a -> Solver a
forall x. x -> Solver x
Solution
(Solution a -> b
f) <*> :: forall a b. Solver (a -> b) -> Solver a -> Solver b
<*> (Solution a
x) = b -> Solver b
forall x. x -> Solver x
Solution (a -> b
f a
x)
(Failure e
e) <*> Solver a
_ = e -> Solver b
forall x e. Exception e => e -> Solver x
Failure e
e
Solver (a -> b)
_ <*> (Failure e
e) = e -> Solver b
forall x e. Exception e => e -> Solver x
Failure e
e
instance Monad Solver where
return :: forall x. x -> Solver x
return = a -> Solver a
forall x. x -> Solver x
forall (f :: * -> *) a. Applicative f => a -> f a
pure
(Solution a
x) >>= :: forall a b. Solver a -> (a -> Solver b) -> Solver b
>>= a -> Solver b
f = a -> Solver b
f a
x
(Failure e
e) >>= a -> Solver b
_ = e -> Solver b
forall x e. Exception e => e -> Solver x
Failure e
e
solve :: Solver x -> x
solve :: forall x. Solver x -> x
solve (Solution x
x) = x
x
solve (Failure e
e) = e -> x
forall a e. Exception e => e -> a
throw e
e
solvable :: Solver r -> Bool
solvable :: forall r. Solver r -> Bool
solvable (Solution r
_) = Bool
True
solvable (Failure e
_) = Bool
False
failure :: Exception e => e -> Solver x
failure :: forall e x. Exception e => e -> Solver x
failure = e -> Solver x
forall x e. Exception e => e -> Solver x
Failure
handle :: Exception e => Solver x -> (e -> Solver x) -> Solver x
handle :: forall e x. Exception e => Solver x -> (e -> Solver x) -> Solver x
handle x :: Solver x
x@(Solution x
_) e -> Solver x
_ = Solver x
x
handle f :: Solver x
f@(Failure e
e) e -> Solver x
h = case SomeException -> Maybe e
forall e. Exception e => SomeException -> Maybe e
fromException (SomeException -> Maybe e) -> SomeException -> Maybe e
forall a b. (a -> b) -> a -> b
$ e -> SomeException
forall e. Exception e => e -> SomeException
toException (e -> SomeException) -> e -> SomeException
forall a b. (a -> b) -> a -> b
$ e
e of
Just e
e' -> e -> Solver x
h e
e'
Maybe e
_ -> Solver x
f