packages feed

deepseq-bounded-0.6.0.0: tests/Foo.hs

-- XXX This file could be cleaned up a lot, but that's
-- not quite a priority at this moment...

  {-# LANGUAGE CPP #-}

-------------------------------------------------------------------------------

#define USE_TRACE 1
-- This so can get an honest comparison for the user-defined datatypes;
-- if this is 0, the NFDataN instances will be derived via GHC.Generics.
-- (The NFData instances are derived in any case.)
#define USE_MANUAL_INSTANCES 0

-------------------------------------------------------------------------------

  module Foo where

-------------------------------------------------------------------------------

-- TABLE OF EXPECTED AND ACTUAL RESULTS
-- (Only recording "BOT" or "ok".)
--
-- The expressions and getters are effectively:
--
-- expBase1 = ([True,False],3,Just "fox")         :: ([Bool],Int,Maybe String)
-- expBase2 = ([True,False],__,Just "fox")        :: ([Bool],Int,Maybe String)
-- expBase3 = ([True,__],3,Just "fox")            :: ([Bool],Int,Maybe String)
-- expBase4 = ([True,__],3,Just __)               :: ([Bool],Int,Maybe String)
-- expBase5 = ([True,False],3,Just ['f',__,'x'])  :: ([Bool],Int,Maybe String)
-- expBase6 = ([True,False],3,Just __)            :: ([Bool],Int,Maybe String)
-- get1 ((x:_),_,_) = x           -- True
-- get2 (_,x,_) = x               -- 3
-- get3 (_,_,x) = fromJust x      -- "fox"
-- get4 (_,_,Just (x:_)) = x      -- 'f'
--
-- These match like Haskell pattern-matching -- the higher will
-- be matched first; the lower will pick up what trickles through.
--
--  (i,j,k)         Expected           Actual
--   * * 1            ok                 ok
--   2 1 2            BOT                BOT
--   * 1 2            ok                 ok
--   * * 2            BOT                BOT
--   * 4 3            BOT                BOT
--   * 5 3            BOT                BOT
--   * * 3            ok                 ok
--   1 1 4            ok                 ok
--   1 2 4            ok                 ok
--   * * 4            BOT                BOT
--   3 * 5            BOT                BOT
--   * 5 5            BOT                BOT
--   * * 5            ok                 ok

-- AND, SOLVED -- by forcing that show!
-- Great! And it's the USE_EXCEPTION branch too, which I prefer
-- in principle.  Now to consider the output...

-- It seems that this difference decides whether escapee exception
-- happens of (3,1,4) or (3,1,5):
--     doit (1+i) j k $! acc
--  -- doit (1+i) j k $ acc
-- What I don't understand is why "show" which is part of get3
-- doesn't force it where the handler can catch it...

-- What a confusion!
-- So, if you also insert some tracing, you can see all (i,j,k)
-- indices traced, yet the exception still occurs.
-- I suppose this is because the acc string isn't forced
-- until later, and meanwhile the trace lines are free to
-- be printed. (This is the explanation for sure.)
--   But just forcing acc is not the same thing?...
-- If force acc, you see nothing at all printed except the
-- trace lines. All of [ABC](3,1,5) are printed, and then
-- the escapee exception rises.

-- And anyhow, now it passes 4 but not 5, and I don't even know
-- how/why? I'm not using overridden fromJust anymore...
-- (i=3 k=5 exception still escapes in any case!)

-- By overriding fromJust I was able to get past expBase4,
-- but i=3 k=5 exception still escapes!...

-- STILL not getting it -- I can run the gamut, just using
-- putStrLn (as we're in IO anyhow since started fussing
-- with exception catching).  And it says we bottom out
-- a few times, with proper interleaving -- but these are
-- only when /get/ requests a __ value; it doesn't seem
-- to do anything when forcen supposedly forces it.
--   And yet, when run with USE_EXCEPTION, we do see these
-- extra bottom-outs -- unfortunately, the "exceptional
-- exception" occurs and the darned thing doesn't run to
-- completion.

-- Having some problems.
-- Same results if use ErrorCall or use custom BottomedOut,
-- namely, get as far as:
--   ( get3 $ forcen 1 expBase4 )
--   t: BottomedOut
-- The "t: " is significant, since normally when hit
-- the "potholes" my exception handler prints only "BottomedOut".
-- And this also terminates the testing.
-- So clearly, my (own, custom, even -- good to know) exception
-- is escaping the handler.  How can this be?  Esp. as it seems
-- nothing much changes from one test to another.
-- The only thing that comes to mind is, we don't catch ASYNCHRONOUS
-- exceptions this way? Why should an asynch. exception be raised
-- in this case. Trying one more thing: define __ to be trace
-- and just trace the fact it was evaluated...

-- XXX Regarding the use of undefined, I think this is not
-- working well for catching all exceptions? Would we have
-- better luck throwing a custom exception type? How do you
-- do that? "throw BottomedOut" in the component of the tuple?...

  import Data.Maybe

  import Control.Exception
--import Control.Monad ( guard )
  import Data.Typeable ( Typeable )
  import Data.Typeable ( typeOf )

--import Util
  import Debug.Trace ( trace )
  import Control.DeepSeq

#if ! HASKELL98_FRAGMENT
  -- Custom exception requires -XDerivingDataTypeable it seems. [?]
  import Bottom
#endif

  import System.IO.Unsafe ( unsafePerformIO )

-------------------------------------------------------------------------------

#if HASKELL98_FRAGMENT
  __ = undefined
#else
-- imported from Bottom (sorry)
#endif

-------------------------------------------------------------------------------

  expN_1 = [__] :: [Int]
  expN_2 = [0,1,__,3] :: [Int]
  expN_3 = (3.4, [5,__,7], True) :: (Float, [Int], Bool)
  expN_4 = (3.4, [5,__,7], __) :: (Float, [Int], Bool)

  getN_1 xs = show $ ()
--getN_1 xs = show $ head xs
--getN_2 xs = show $ (xs!!1)
  getN_2 xs = show $ (xs!!3)
  getN_3 (_,xs,_) = show $ (xs!!2)

-------------------------------------------------------------------------------

#if 0

  -- Should be able to dodge the third component with a pattern.
--expP_1 = (3.4, [5,__,7], True) :: (Float, [Int], Bool)
  expP_1 = (3.4, [5,__,7], __) :: (Float, [Int], Bool)
  patP_1 = Node (TR [typeOf ((__,__,__)::(Float, [Int], Bool))])
             [ Node (TR [typeOf (__::Bool)]) []
--           [ Node (TR [typeOf (__::Float)]) []
--           [ Node (NTR [typeOf (__::Bool)]) []
--           [ Node (NTR [typeOf (__::Float)]) []
--           , Node WS []
             , Node (TW [typeOf ([__]::[Int])]) []
--           , Node (TR [typeOf ([__]::[Int])]) []
--           , Node (TR [typeOf ([__]::[Int])]) [ Node WS [], Node WS [] ]  -- why not?
             , Node WW []
--           , Node I []
             ]
  getP_1 (_,xs,_) = show $ (xs!!2)

  expP_2 = 23 :: Int
--expP_2 = [1,__,3] :: [Int]
  patP_2 = Node WW []
--patP_2 = Node (TR [typeOf ([__]::[Int])]) []
  getP_2 x = show x

#if 1
-- Fuck, this works too... (the only one of all of 'em, except bare 23)
-- See NFDataP.hs for expansion of PatNode constructors...
-- (It's hardly going to be that useful if you have to specify
-- one constructor per node in whole data structure, rather than
-- just match the top bit you want as one expects with patterns.)
-- So I'm basically committed to this expansion...
  expP_3 = (3.4, (5,__), __) :: (Float, (Int,Int), Bool)
  patP_3 = Node (TR [typeOf ((__,__,__)::(Float, (Int,Int), Bool))])
#if 0
             [ Node W []
             , Node I [ Node W [], Node W [] ]  -- works
--           , Node I []                        -- doesn't work
             , Node W []
             ]
#else
             [ Node WR []
             , Node WR [ Node WR [], Node WR [] ]  -- works
--           , Node WR []                        -- doesn't work
             , Node WR []
             ]
#endif
  getP_3 (_,(_,x),_) = show x
#else
  expP_3 = (3.4, (5,__), __) :: (Float, (Int,Int), Bool)
  patP_3 = Node (T [typeOf ((__,__,__)::(Float, (Int,Int), Bool))])
             [ Node (T [typeOf (__::Float)]) []
--           [ Node W []
             , Node (T [typeOf ((__,__)::(Int,Int))]) []
             , Node I []
             ]
  getP_3 (_,(_,x),_) = show x
#endif

#endif

-------------------------------------------------------------------------------

  expBase1 = ([True,False],3,Just "fox")         :: ([Bool],Int,Maybe String)
  expBase2 = ([True,False],__,Just "fox")        :: ([Bool],Int,Maybe String)
  expBase3 = ([True,__],3,Just "fox")            :: ([Bool],Int,Maybe String)
  expBase4 = ([True,__],3,Just __)               :: ([Bool],Int,Maybe String)
  expBase5 = ([True,False],3,Just ['f',__,'x'])  :: ([Bool],Int,Maybe String)
  expBase6 = ([True,False],3,Just __)            :: ([Bool],Int,Maybe String)

#if 1
  get1 ((x:_),_,_) = show x         -- True
  get2 (_,x,_) = show x             -- 3
#if 0
#if 0
  get3 (_,_,x) = do
                    es <- myFromJust x  -- "fox"
                    case es of
                     Left () -> return ""
                     Right s -> return $! show s
--get3 (_,_,x) = show $! myFromJust x  -- "fox"
#else
  get3 (_,_,x) = return $! show $! fromJust x  -- "fox"
--get3 (_,_,x) = return $ show $ fromJust x  -- "fox"
#endif
#else
  get3 ijk (_,_,x) = force $ show $ fromJust x  -- "fox"
--get3 ijk (_,_,x) = trace ("A"++show ijk) ( force $ show $! trace ("B"++show ijk) $ fromJust $! trace ("C"++show ijk) $ x )  -- "fox"
--get3 (_,_,x) = show $! fromJust x  -- "fox"
--get3 (_,_,x) = show $ fromJust x  -- "fox"
#endif
  get4 (_,_,Just (x:_)) = show x    -- 'f'
#else
  get1 ((x:_),_,_) = x       -- True
  get2 (_,x,_) = x           -- 3
  get3 (_,_,x) = fromJust x  -- "fox"
  get4 (_,_,Just (x:_)) = x  -- 'f'
#endif

#if 0
  -- oops, these are just what you DON'T want!
  get1 (_,x,_) = x  -- 3
  get2 (_:x:_) = x  -- False
  get3 (_,_,x) = fromJust x  -- "fox"
  get4 (_,_,(_:x:_)) = x  -- 'o'
#endif

-------------------------------------------------------------------------------