{-# LANGUAGE TypeFamilies #-}
module Control.Shell.Control
( module Control.Monad
, Guard (..)
, guard, when, unless, orElse
) where
import Control.Shell.Internal
import Control.Monad hiding (when, unless, guard)
orElse :: Shell a -> Shell a -> Shell a
orElse a b = do
ex <- try a
case ex of
Right x -> return x
_ -> b
class Guard guard where
type Result guard
assert :: String -> guard -> Shell (Result guard)
instance Guard (Either l r) where
type Result (Either l r) = r
assert _ (Right x) = return x
assert desc _ = fail desc
instance Guard (Maybe a) where
type Result (Maybe a) = a
assert _ (Just x) = return x
assert desc _ = fail desc
instance Guard Bool where
type Result Bool = ()
assert _ True = return ()
assert desc _ = fail desc
instance Guard a => Guard (Shell a) where
type Result (Shell a) = Result a
assert desc m = m >>= \x -> assert desc x
guard :: Guard g => g -> Shell (Result g)
guard = assert "Guard failed!"
when :: Guard g => g -> Shell () -> Shell ()
when g m = do
res <- try (guard g)
case res of
Right _ -> m
_ -> return ()
unless :: Guard g => g -> Shell () -> Shell ()
unless g m = void (guard g) `orElse` m