packages feed

caledon-0.0.0.0: Choice.hs

{-# LANGUAGE 
 DeriveFunctor, 
 FlexibleContexts,
 TypeSynonymInstances
 #-}

module Choice where
import Control.Monad
import Data.Functor
import Control.Applicative
import Control.Monad.Error (ErrorT, runErrorT)
import Control.Monad.Error.Class (catchError, throwError, MonadError)
import Control.Monad.State.Class
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
import Data.Maybe

data Choice a = Choice a :<|>: Choice a 
              | Fail String
              | Success a
              deriving (Functor)

instance Monad Choice where 
  fail a = Fail a
  return = Success
  Fail a >>= _ = Fail a
  (m :<|>: m') >>= f = (m >>= f) :<|>: (m' >>= f)
  Success a >>= f = f a
  
instance Applicative Choice where  
  pure = Success
  mf <*> ma = mf >>= (<$> ma)
  
instance Alternative Choice where
  empty = Fail ""
  (<|>) = (:<|>:)
        
instance MonadPlus Choice where        
  mzero = Fail ""
  mplus = (:<|>:)
  
class RunChoice m where  
  runError :: m a -> Either String a
  
instance RunChoice Choice where
  runError chs = case dropWhile notSuccess lst of
    [] -> case dropWhile notFail lst of 
      Fail a:_ -> Left a
      _ -> error "this result makes no sense"
    (Success a):_ -> Right a
    _ -> error "this result makes no sense"
    where lst = chs:queue lst 1
          
          queue l 0 = []
          queue ((a :<|>: b):l) q = a:b:queue l (q + 1)
          queue (_:l) q = queue l (q - 1)
          
          notFail (Fail a) = False
          notFail _ = True
          
          notSuccess (Success a) = False
          notSuccess _ = True
  
appendErr :: (MonadError String m) => String -> m a -> m a
appendErr s m = catchError m $ \s' -> throwError $ s' ++ "\n" ++ s
  
instance MonadError String Choice where
  throwError a = Fail a
  catchError try1 foo_try2 = case runError try1 of
    Left s -> foo_try2 s
    Right a -> Success a

getNew :: (MonadState Integer m) => m String
getNew = do 
  st <- get
  let n = 1 + st
  put n
  return $! show n