-- Here is an example of using an "exception monad" -- The idea is to write the attribute system for recognizing based numbers -- ... this uses an example in Louden data BN = Bn NM BC deriving Show data BC = Octal | Decimal deriving Show data NM = Snm DG NM | Znm DG deriving Show data DG = D0|D1|D2|D3|D4|D5|D6|D7|D8|D9 deriving Show data ANS a = Ans a | Err String deriving Show instance Monad ANS where return x = Ans x Err st >>= q = Err st Ans x >>= q = q x base_num:: BN -> ANS Int base_num (Bn n b) = do d <- base_ch b n' <- num n d return n' base_ch:: BC -> ANS Int base_ch(Octal) = do return 8 base_ch(Decimal) = do return 10 num:: NM -> Int -> ANS Int num (Snm d n) b = do d' <- digit d b n' <- num n b return (b*n' + d') num (Znm d) b = do d' <- digit d b return d' digit:: DG -> Int -> ANS Int digit D0 b = do return 0 digit D1 b = do return 1 digit D2 b = do return 2 digit D3 b = do return 3 digit D4 b = do return 4 digit D5 b = do return 5 digit D6 b = do return 6 digit D7 b = do return 7 digit D8 b = if 8 < b then do return 8 else Err "Digit is not base 8!" digit D9 b = if 8 < b then do return 9 else Err "Digit is not base 8!" base_num (Bn (Snm D7 (Snm D9 (Znm D3))) Octal)