{-# LANGUAGE RebindableSyntax, NPlusKPatterns #-} module Main where { -- import Prelude; import qualified Prelude; import Prelude(String,undefined,Maybe(..),IO,putStrLn, Integer,(++),Rational, (==), (>=) ); import Prelude(Monad(..),Applicative(..),Functor(..),MonadFail(..)); import Control.Monad(ap, liftM); debugFunc :: String -> IO a -> IO a; debugFunc s ioa = (putStrLn ("++ " ++ s)) Prelude.>> (ioa Prelude.>>= (\a -> (putStrLn ("-- " ++ s)) Prelude.>> (Prelude.return a) )); newtype TM a = MkTM {unTM :: IO a}; instance (Functor TM) where { fmap = liftM; }; instance (Applicative TM) where { pure = return; (<*>) = ap; }; instance (Monad TM) where { return a = MkTM (debugFunc "return" (Prelude.return a)); (>>=) ma amb = MkTM (debugFunc ">>=" ((Prelude.>>=) (unTM ma) (\a -> unTM (amb a)))); (>>) ma mb = MkTM (debugFunc ">>" ((Prelude.>>) (unTM ma) (unTM mb))); }; instance (MonadFail TM) where { fail s = MkTM (debugFunc "fail" (Prelude.return undefined)); }; preturn a = MkTM (Prelude.return a); fromInteger :: Integer -> Integer; fromInteger a = a Prelude.+ a Prelude.+ a Prelude.+ a Prelude.+ a; -- five times fromRational :: Rational -> Rational; fromRational a = a Prelude.+ a Prelude.+ a; -- three times negate :: a -> a; negate a = a; -- don't actually negate (-) :: a -> a -> a; (-) x y = y; -- changed function test_do f g = do { f; -- >> Just a <- g; -- >>= (and fail if g returns Nothing) return a; -- return }; test_fromInteger = 27; test_fromRational = 31.5; test_negate a = - a; test_fromInteger_pattern a@1 = "1=" ++ (Prelude.show a); test_fromInteger_pattern a@(-2) = "(-2)=" ++ (Prelude.show a); test_fromInteger_pattern (a + 7) = "(a + 7)=" ++ Prelude.show a; test_fromRational_pattern a@0.5 = "0.5=" ++ (Prelude.show a); test_fromRational_pattern a@(-0.7) = "(-0.7)=" ++ (Prelude.show a); test_fromRational_pattern a = "_=" ++ (Prelude.show a); tmPutStrLn s = MkTM (putStrLn s); doTest :: String -> TM a -> IO (); doTest s ioa = (putStrLn ("start test " ++ s)) Prelude.>> (unTM ioa) Prelude.>> (putStrLn ("end test " ++ s)); main :: IO (); main = (doTest "test_do failure" (test_do (preturn ()) (preturn Nothing)) ) Prelude.>> (doTest "test_do success" (test_do (preturn ()) (preturn (Just ()))) ) Prelude.>> (doTest "test_fromInteger" (tmPutStrLn (Prelude.show test_fromInteger)) -- 27 * 5 = 135 ) Prelude.>> (doTest "test_fromRational" (tmPutStrLn (Prelude.show test_fromRational)) -- 31.5 * 3 = 189%2 ) Prelude.>> (doTest "test_negate" (tmPutStrLn (Prelude.show (test_negate 3))) -- 3 * 5 = 15, non-negate ) Prelude.>> (doTest "test_fromInteger_pattern 1" (tmPutStrLn (test_fromInteger_pattern 1)) -- 1 * 5 = 5, matches "1" ) Prelude.>> (doTest "test_fromInteger_pattern (-2)" (tmPutStrLn (test_fromInteger_pattern (-2))) -- "-2" = 2 * 5 = 10 ) Prelude.>> (doTest "test_fromInteger_pattern 9" (tmPutStrLn (test_fromInteger_pattern 9)) -- "9" = 45, 45 "-" "7" = "7" = 35 ) Prelude.>> (doTest "test_fromRational_pattern 0.5" (tmPutStrLn (test_fromRational_pattern 0.5)) -- "0.5" = 3%2 ) Prelude.>> (doTest "test_fromRational_pattern (-0.7)" (tmPutStrLn (test_fromRational_pattern (-0.7))) -- "-0.7" = "0.7" = 21%10 ) Prelude.>> (doTest "test_fromRational_pattern 1.7" (tmPutStrLn (test_fromRational_pattern 1.7)) -- "1.7" = 51%10 ); }