{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE Safe #-} module Data.Tickle.IsolateError( -- * Data type IsolateError -- * Reduction , isolateError -- * Prisms , _NegativeSize , _IsolateXFail , _UnexpectedConsumed ) where import Control.Lens.Prism(prism') import Control.Lens.Type(Prism') import Data.Eq(Eq) import Data.Function(const) import Data.Functor(Functor(fmap)) import Data.Functor.Extend(Extend(extended, duplicated)) import Data.Int(Int) import Data.Maybe(Maybe(Just, Nothing)) import Data.Ord(Ord) import Data.Tuple(uncurry) import Prelude(Show) -- $setup -- >>> import Control.Lens((#)) -- >>> import Control.Lens.Fold((^?)) -- >>> import Data.List(reverse) -- >>> import Prelude(Num((+), (*))) data IsolateError e = NegativeSize | IsolateXFail e | UnexpectedConsumed Int Int deriving (Eq, Ord, Show) -- | -- -- >>> isolateError 7 (\_ -> 8) (\_ _ -> 9) (_NegativeSize # ()) -- 7 -- -- >>> isolateError 7 (+10) (\_ _ -> 9) (_IsolateXFail # 99) -- 109 -- -- >>> isolateError 7 (\_ -> 8) (+) (_UnexpectedConsumed # (12, 14)) -- 26 isolateError :: a -> (e -> a) -> (Int -> Int -> a) -> IsolateError e -> a isolateError n _ _ NegativeSize = n isolateError _ f _ (IsolateXFail e) = f e isolateError _ _ u (UnexpectedConsumed m n) = u m n -- | Map a function on the possible failure. -- -- >>> fmap (+1) (_NegativeSize # () :: IsolateError Int) -- NegativeSize -- -- >>> fmap reverse (_IsolateXFail # "abc") -- IsolateXFail "cba" -- -- >>> fmap (+1) (_UnexpectedConsumed # (7, 8) :: IsolateError Int) -- UnexpectedConsumed 7 8 instance Functor IsolateError where fmap _ NegativeSize = NegativeSize fmap f (IsolateXFail e) = IsolateXFail (f e) fmap _ (UnexpectedConsumed m n) = UnexpectedConsumed m n -- | Duplicate on the possible failure. -- -- >>> extended (isolateError 12 (+10) (*)) (_IsolateXFail # 99) -- IsolateXFail 109 -- -- >>> extended (isolateError 12 (+10) (*)) (_UnexpectedConsumed # (12, 13)) -- UnexpectedConsumed 12 13 -- -- >>> extended (isolateError 12 (+10) (*)) (_NegativeSize # ()) -- NegativeSize instance Extend IsolateError where extended _ NegativeSize = NegativeSize extended f i@(IsolateXFail _) = IsolateXFail (f i) extended _ (UnexpectedConsumed m n) = UnexpectedConsumed m n duplicated NegativeSize = NegativeSize duplicated i@(IsolateXFail _) = IsolateXFail i duplicated (UnexpectedConsumed m n) = UnexpectedConsumed m n -- | -- -- >>> _NegativeSize # () -- NegativeSize -- -- >>> (_NegativeSize # ()) ^? _NegativeSize -- Just () -- -- >>> (_IsolateXFail # 8) ^? _NegativeSize -- Nothing -- -- >>> (_UnexpectedConsumed # (12, 13)) ^? _NegativeSize -- Nothing _NegativeSize :: Prism' (IsolateError e) () _NegativeSize = prism' (const NegativeSize) (\x -> case x of NegativeSize -> Just () _ -> Nothing) -- | -- -- >>> _IsolateXFail # 8 -- IsolateXFail 8 -- -- >>> (_NegativeSize # ()) ^? _IsolateXFail -- Nothing -- -- >>> (_IsolateXFail # 8) ^? _IsolateXFail -- Just 8 -- -- >>> (_UnexpectedConsumed # (12, 13)) ^? _IsolateXFail -- Nothing _IsolateXFail :: Prism' (IsolateError e) e _IsolateXFail = prism' IsolateXFail (\x -> case x of IsolateXFail e -> Just e _ -> Nothing) -- | -- -- >>> _UnexpectedConsumed # (12,13) -- UnexpectedConsumed 12 13 -- -- >>> (_NegativeSize # ()) ^? _UnexpectedConsumed -- Nothing -- -- >>> (_IsolateXFail # 8) ^? _UnexpectedConsumed -- Nothing -- -- >>> (_UnexpectedConsumed # (12, 13)) ^? _UnexpectedConsumed -- Just (12,13) _UnexpectedConsumed :: Prism' (IsolateError e) (Int, Int) _UnexpectedConsumed = prism' (uncurry UnexpectedConsumed) (\x -> case x of UnexpectedConsumed l m -> Just (l, m) _ -> Nothing)