packages feed

uuagc-0.9.51: src/LOAG/Result.hs

{-# LANGUAGE FlexibleInstances #-}

-- Module for containing results in LOAG tests
module LOAG.Result where

import Control.Applicative
import Control.Monad (liftM, ap, MonadPlus(..))
import Control.Monad.Trans (lift, MonadTrans(..))
import Control.Monad.State (MonadState(..))
import Control.Monad.ST
import ErrorMessages as Err

import LOAG.Graphs

type LOAG s a = ResultT (ST s) a

data Result a = Give  a     
                -- the edge that caused the cyclep of ctype 
              | Cycle Edge Cycle CType
              | Limit
              | NotLOAG
    deriving (Show)            

fromGive :: Result a -> a
fromGive (Give a) = a
fromGive _        = error "fromGive"

data CType = T1 | T2 
           | T3 [Edge] -- completing edges from which to select candidates
    deriving (Show)
-- | Inspired by ErrorT
newtype ResultT m a = Result { runResult :: m (Result a) }

instance Monad m => Functor (ResultT m) where
  fmap = liftM

instance Monad m => Applicative (ResultT m) where
  pure  = return
  (<*>) = ap

instance (Monad m) => Monad (ResultT m) where
    return               = Result . return . Give
    (>>=) rt f = Result $ do
        ma <- runResult rt
        case ma of 
            Give a      -> runResult (f a)
            Cycle e c t -> return $ Cycle e c t 
            Limit       -> return $ Limit
            NotLOAG     -> return $ NotLOAG

instance MonadTrans ResultT where
    lift m = Result $ m >>= return . Give
instance MonadState s (ResultT (ST s)) where
    get = get
    put = put

instance Monad m => Alternative (ResultT m) where
    (<|>) = mplus
    empty = mzero

instance (Monad m) => MonadPlus (ResultT m) where
    mzero = Result $ return NotLOAG
    mplus a b = Result $ do
        ma <- runResult a 
        case ma of
            Give a  -> return $ Give a
            f       -> do   mb <- runResult b
                            case mb of 
                              Give b  -> return $ Give b
                              _       -> return f

-- | Return an error (from detecting a cycle) in the ResultT monad
throwCycle :: (Monad m) => Edge -> Cycle -> CType -> ResultT m a
throwCycle e c t = Result $ return $ Cycle e c t

throwNotLOAG :: (Monad m) => ResultT m a
throwNotLOAG = Result $ return NotLOAG