module Debug.NoHoed
( observe
, runO
, printO
, testO
, observeBase
, Observable(..)
, Parent(..)
, Generic(..)
, send
, ObserverM(..)
, (<<)
) where
import GHC.Generics
import System.IO.Unsafe
import Control.Monad
observe :: String -> a -> a
observe _ = id
runO :: IO a -> IO ()
runO program = do
  program
  return ()
printO :: (Show a) => a -> IO ()
printO expr = print expr
testO :: Show a => (a->Bool) -> a -> IO ()
testO p x = putStrLn $ if (p x) then "Passed 1 test."
                                else " *** Failed! Falsifiable: " ++ show x
data Parent = Parent
class Observable a where
        observer  :: a -> Parent -> a 
        default observer :: (Generic a) => a -> Parent -> a
        observer x _ = x
        constrain :: a -> a -> a
        default constrain :: (Generic a) => a -> a -> a
        constrain x _ = x
observeBase :: a -> Parent -> a 
observeBase x _ = x
constrainBase :: a -> a -> a
constrainBase x _ = x
newtype ObserverM a = ObserverM { runMO :: Int -> Int -> (a,Int) }
instance Functor ObserverM where
    fmap  = liftM
#if __GLASGOW_HASKELL__ >= 710
instance Applicative ObserverM where
    pure  = return
    (<*>) = ap
#endif
instance Monad ObserverM where
        return a = ObserverM (\ c i -> (a,i))
        fn >>= k = ObserverM (\ c i ->
                case runMO fn c i of
                  (r,i2) -> runMO (k r) c i2
                )
(<<) :: (Observable a) => ObserverM (a -> b) -> a -> ObserverM b
fn << a = do {fn' <- fn; return (fn' a)}
send :: String -> ObserverM a -> Parent -> a
send _ fn context =
  unsafePerformIO $ do { let (r,portCount) = runMO fn 0 0
                       ; return r
                       }
instance Observable Int where
  observer  = observeBase
  constrain = constrainBase
                                 
instance Observable Bool where
  observer  = observeBase
  constrain = constrainBase
                                 
instance Observable Integer where
  observer  = observeBase
  constrain = constrainBase
                                 
instance Observable Float where
  observer  = observeBase
  constrain = constrainBase
                                 
instance Observable Double where
  observer  = observeBase
  constrain = constrainBase
                                 
instance Observable Char where
  observer  = observeBase
  constrain = constrainBase
                                 
instance Observable () where
  observer  = observeBase
  constrain = constrainBase
instance (Observable a) => Observable [a] where
  observer  = observeBase
  constrain = constrainBase