last
last :: IterV el (Maybe el) last = Cont (step Nothing) where step :: (Maybe el) -> (StreamG el -> IterV el (Maybe el)) step _ (El el) = Cont (step (Just el)) step prev Empty = Cont (step prev) step prev EOF = Done prev EOF
last
last :: IterV el (Maybe el) last = Cont (step Nothing) where step :: (Maybe el) -> (StreamG el -> IterV el (Maybe el)) step _ (El el) = Cont (step (Just el)) step prev Empty = Cont (step prev) step prev EOF = Done prev EOF
Divergent are iteratees which never become Done state, not even when it is receiving EOF.
*Main> run $ enum diverge "abcadf" Nothing
diverge :: IterV el Int diverge = Cont step where step :: (StreamG el -> IterV el Int) step e = Cont step
run $ enum diverge "abcadf" -- This step is bound to diverge run $ enum (Cont step) "abcadf" run $ enum (step (El 'a')) "bcadf" run $ enum (Cont step) "bcadf" run $ enum (Cont step) "bcadf" run $ enum (step (El 'b')) "cadf" run $ enum (Cont step) "cadf" run $ enum (step (El 'c')) "adf" run $ enum (Cont step) "adf" run $ enum (step (El 'a')) "adf" ... run $ enum (Cont step) "f" run $ enum (step (El 'f')) [] -- Enum returns the iteratee when the feeding array becomes empty run $ (step (El 'f')) run $ Cont step -- using the secodn rule of run run' (step EOF) run' (Cont step) -- Usign the second rule of run' Nothing
Let's perform the evaluation on head and drop.
drop :: Int -> IterV el () drop 0 = Done () Empty drop n = Cont step where step (El _) = drop (n-1) step Empty = Cont step step EOF = Done () EOF head :: IterV el (Maybe el) head = Cont step where step (El el) = Done (Just el) Empty step Empty = Cont step step EOF = Done Nothing EOF
This is goal
*Main> run $ enum (drop 1 >> head) "abc" Just (Just 'b')
The following steps are to generate the goal above.
run $ enum (drop 1 >> head) "abc" run $ enum (drop 1 >>= (\x -> head)) "abc" run $ enum (case (drop 1) of Done x e -> case ((\x -> head) x) of Done x' _ -> Done x' e Cont k -> k e Cont k -> Cont (\str ->((k str) >>= (\x -> head))) ) "abc" -- Using drop rule. The step is bound to "drop 1" run $ enum (case (Cont step) of Done x e -> case ((\x -> head) x) of Done x' _ -> Done x' e Cont k -> k e Cont k -> Cont (\str ->((k str) >>= (\x -> head))) ) "abc" run $ enum (Cont (\e ->((step e) >>= (\x -> head))) ) "abc" -- enum feeds element to the iteratee, when it is Cont run $ enum ((step (El 'a')) >>= (\x -> head))) ) "bc" -- As the step is from "drop 1", it is evaluated to "drop 1-1)" run $ enum (drop (1-1) >>= (\x -> head))) ) "bc" run $ enum (drop 0 >>= (\x -> head))) ) "bc" run $ enum (Done () Empty >>= (\x -> head))) ) "bc" run $ enum (case ((\x -> head) () of Done x' _ -> Done x' Empty Cont k -> k Empty)) ) "bc" run $ enum (case head of Done x' _ -> Done x' Empty Cont k -> k Empty)) ) "bc" -- step is bound to head run $ enum (case (Cont step) of Done x' _ -> Done x' Empty Cont k -> k Empty)) ) "bc" run $ enum (step Empty) "bc" -- This step is bound to head run $ enum (Cont step) "bc" run $ enum (Cont step) "bc" run $ enum (step (El 'b')) "c" -- Enum returns the iteratee if it is Done run $ enum (Done (Just 'b') Empty) "c" run $ (Done (Just 'b') Empty) Just (Just 'b')
As I'm not clear about how iteratees work, here I write down the step of "length" iteratee.
length :: IterV el Int length = Cont (step 0) where step acc (El _) = Cont (step (acc+1)) step acc Empty = Cont (step acc) step acc EOF = Done acc EOF enum :: IterV el a -> [el] -> IterV el a enum i [] = i enum i@(Done _ _) _ = i enum (Cont k) (x:xs) = enum (k (El x)) xs run :: IterV el a -> Maybe a run (Done x _) = Just x run (Cont k) = run' (k EOF) where run' (Done x _) = Just x run' _ = Nothing
*Main> run $ enum length "abc" Just 3
-- as the first operation of run is pattern match, we have to evaluate the arguments run $ enum length "abc" -- as the first operation of enum is pattern match, we have to evaluate the arguments run $ enum (Cont (step 0)) "abc" -- Using the last equation of enum run $ enum ((step 0) El 'a') "bc" -- as the first operation of enum is pattern match, evaluate the first argument -- Here, it discards the 'a'. Using the first rule of step. run $enum (Cont (step (0+1))) "bc" -- Continues... run $ enum (step (0+1) (El 'b')) "c" -- Using the last rule of enum run $ enum (Cont (step (0+1+1))) "c" -- definition of step as we need pattern match for the first argument run $ enum (step (0+1+1) (El 'c')) [] -- Using the last rule of enum run $ enum (step (0+1+1) (El 'c')) [] -- Using the last rule of enum run $ step (0+1+1) (El 'c') -- Using the first rule of enum. As we need pattern match against the first argument of run, we continue evaluate the right side of '$' run $ Cont (step (0+1+1+1)) -- Using first rule of step run' (step (0+1+1+1) EOF) -- Using second rule of run run' (Done (0+1+1+1) EOF) -- The first argument of run' needs to be evaluated Just (0+1+1+1) -- using the first rule of run' Just 3 -- evaluate to output the result
Around p.27 of Monad.Reader#16.
type EnumeratorM el m a = IterV el a -> m (IterV el a) enumHandle :: Handle -> EnumeratorM Char IO a -- IterV Char a -> m (IterV Char a) enumHandle h iter = loop iter where loop :: IterV Char a -> IO (IterV Char a) loop i@(Done _ _) = return i loop i@(Cont k) = do isEOF <- hIsEOF h if isEOF then return i else do e <- hGetChar h loop . k . El $ e -- k :: (StreamG Char -> IterV Char a) enumFile :: FilePath -> EnumeratorM Char IO a -- IterV Char a -> m (IterV Char a) enumFile fp i = bracket (openFile fp ReadMode) (hClose) (flip enumHandle i) lengthOfTwoFiles :: FilePath -> FilePath -> IO (Maybe Int) lengthOfTwoFiles fp1 fp2 = fmap run $ ((enumFile fp1) >=> (enumFile fp2)) length -- enumFile fp1 :: IterV Char a -> IO (IterV Char a) -> x -> m x -- enumFile fp2 :: IterV Char a -> IO (IterV Char a) -> x -> m x -- length :: IterV el Int -> x -- (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
The last fmap works over "IO (IterV Char Int)", the right side of "$"
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c) f >=> g = \x -> f x >>= g
Once we define ">>=" operator, we can use this left-to-right Kleisli composition using the default implementation.
I'm trying to understand Iteratee section in [themonadreader.files.wordpress.com/2010/05/issue16.pdf:title=Monad Reader 16].
alternates :: IterV el [el] alternates = fmap catMaybes . sequence . replicate 5 $ drop1keep1 -- replicate 5 $drop1keep1 :: [IterV el (Maybe el)] -- sequence . replicate 5 $ drop1keep1 :: IterV el [ Maybe el ] Let's say this as X -- fmap catMaybes X :: IterV el (([Maybe a] -> [a]) [ Maybe el ]) -- fmap catMaybes X :: IterV el [ el ]
Suppose we have a type "V X Y Z", this should be understood as "(V X Y) Z". If V X Y is monad, the type has value Z.
z <- vxyz :: V X Y Z z
The type of z is Z. And return always wrap a value with appropriate "context" (Monadic type) like:
somefunc :: V X Y Z somefunc = do return z
Here, without specifying V X Y, "return" generates Monadic value of type "V X Y Z"