iteratee Strange behaviour eneeCheckIfDone

Michael Baikov manpacket at gmail.com
Fri Jul 29 02:30:05 BST 2011


This is an implementation of typesafe iteratee exceptions. Some
functions are only implemented on the typelevel, some have complete
implementation.

Typelevel tags are applied to Iteratee data type which gets one extra
type parameter and a new name - IterateeE (just to show that this is a
new type). This makes more sense than tagging streams, because seeks
and other actions are performed by Iteratees and handled by
Enumeratees.

In this implementation each eneeCheckIfDoneHandle can handle only one
exception type - this is also makes sense - if your exceptions are
related then you should make them into one type, If they are separate
- maybe they should not be handled in single place.

Here i am reimplemented some stuff from Control.Exception module, but
in production code we should use code from Control.Exception.

{-# LANGUAGE ExistentialQuantification
    , EmptyDataDecls
    , FlexibleInstances
    , RankNTypes
    , TypeSynonymInstances
    , FlexibleContexts
    , DeriveDataTypeable
    , OverlappingInstances
    , MultiParamTypeClasses #-}
import Data.Typeable
import Data.NullPoint

type FileOffset = Int

-- My Iteratee ----------------------------------------------------------------------------
{{{

data Stream c =
  EOF -- (Maybe SomeException)
  | Chunk c
  deriving (Show, Typeable)

newtype IterateeE e s m a = IterateeE { runIter :: forall r.
          (a -> Stream s -> m r) ->
          ((Stream s -> IterateeE e s m a) -> SomeException -> m r) ->
          m r}
type EnumerateeE eFrom eTo sFrom sTo m a =
        IterateeE eTo sTo m a ->
        IterateeE eFrom sFrom m (IterateeE eTo sTo m a)


eneeCheckIfDoneHandle :: (Monad m, NullPoint elo, NullPoint eli,
Exception ex) =>
 ((Stream eli -> IterateeE ei eli m a) -> ex -> IterateeE (Caught ex
e) elo m (IterateeE e eli m a)) ->
 ((Stream eli -> IterateeE ei eli m a) -> SomeException -> IterateeE
(Caught ex e) elo m (IterateeE e eli m a))
 -> EnumerateeE e (Caught ex e) elo eli m a

eneeCheckIfDoneHandle = undefined
{-
eneeCheckIfDoneHandle h f inner = IterateeE $ \od oc ->
   let onDone x s = od (idone x s) (Chunk empty)
       onCont k e = case cast e of
                        Nothing -> runIter (f k e) od oc
                        Just ex -> runIter (h k ex) od oc
   in runIter inner onDone onCont
-}


joinI ::
 (Monad m, NullPoint s) =>
  IterateeE e s m (IterateeE e' s' m a)
  -> IterateeE e s m a
joinI = undefined
{-
joinI = (>>=
  \inner -> IterateeE $ \od oc ->
  let onDone  x _        = od x (Chunk empty)
      onCont = undefined
--      onCont  k Nothing  = runIter (k (EOF Nothing)) onDone onCont'
--      onCont  _ (Just e) = runIter (throwErr e) od oc
--      onCont' _ e        = runIter (throwErr (fromMaybe excDivergent e)) od oc
  in runIter inner onDone onCont)
-}

idone :: Monad m => a -> Stream s -> IterateeE e s m a
idone a s = IterateeE $ \onDone _ -> onDone a s

icont :: (Stream s -> IterateeE e s m a) -> SomeException -> IterateeE e s m a
icont k e = IterateeE $ \_ onCont -> onCont k e

liftI :: (Stream s -> IterateeE e s m a) -> IterateeE e s m a
liftI = flip icont nothingToWorryAbout

nothingToWorryAbout :: SomeException
nothingToWorryAbout = toException NothingToWorryAbout

throwRecoverableErr :: (Throws ex e, Exception ex) =>
        ex -> (Stream s -> IterateeE e s m a) -> IterateeE e s m a
throwRecoverableErr e k = IterateeE $ \_ onCont -> onCont k (toException e )

identity :: (Monad m, NullPoint s) => IterateeE e s m ()
identity = idone () (Chunk empty)

-------------------------------------------------------------------------------------------
}}}

-- my Exception {{{
-- first let's define Exception class with default implementations of
toException/fromException
class (Typeable e, Show e) => Exception e where
    toException :: e -> SomeException
    toException = SomeException

    fromException :: SomeException -> Maybe e
    fromException (SomeException e) = cast e

-- One constructor for that class
data SomeException = forall e. Exception e => SomeException e
    deriving (Typeable)

-- and the Show instance, since this is not haskell-98 type anymore
instance Show SomeException where
    show (SomeException e) = show e
-- }}}

-- Some Test cases {{{

data SeekException = SeekException FileOffset deriving (Typeable, Show)
instance Exception SeekException

data ResetException = ResetException deriving (Typeable, Show)
instance Exception ResetException

seek :: (Monad m, NullPoint s, Throws SeekException e) => IterateeE e s m ()
seek = throwRecoverableErr (SeekException 1000) (const identity)

reset :: (Monad m, NullPoint s, Throws ResetException e) => IterateeE e s m ()
reset = throwRecoverableErr (ResetException) (const identity)

muncher :: Monad m => IterateeE e s m ()
muncher = liftI go
    where
        go c = liftI go

resetE :: Monad m => EnumerateeE ei (Caught ResetException ei) [s] [s] m a
resetE = undefined
{-resetE = eneeCheckIfDoneHandle h (icont . go)
    where
        go k c = eneeCheckIfDoneHandle h (icont . go) (k c)
        h = error "Got reset message"
-}
seekE :: Monad m => EnumerateeE ei (Caught SeekException ei) [s] [s] m a
seekE = undefined
{-seekE = eneeCheckIfDoneHandle h (icont . go)
    where
        go k c = eneeCheckIfDoneHandle h (icont . go) (k c)
        h = error "Got seek message"-}
-- }}}

{-
results:

resetE reset     -- typchecks
resetE muncher   -- typechercks
resetE seek      -- fails
seekE reset      -- fails
seekE seek       -- typechecks
resetE (joinI $ seekE $ head [reset, seek, muncher]) fails
joinI $ seekE $ head [reset, seek, muncher] -- fails


-}


-- Typelevel magic {{{
data Caught e l
class    Exception e => Throws e s
instance Exception e => Throws e (Caught e l)
instance Throws e l  => Throws e (Caught e1 l)
--instance Throws e l  => Throws e (Caught e1 l)
instance Exception e => Throws e (Caught SomeException l)
data NothingToWorryAbout = NothingToWorryAbout deriving (Show, Typeable)
instance Exception NothingToWorryAbout
-- }}}



More information about the Iteratee mailing list