Oleg wrote about converting an arbitrary traversable into a zipper.

His code uses delimited continuations, and I puzzled a while (years...) before starting to understand what was going on.

I just read Yield: mainstream delimited continuations.

It looked to me like I could easily change Oleg's zipper can be expressed using "yield" which gives a different view, that I think I might have understood more easily - because I know yield from other languages, and don't properly have my head around continuations (which is basically the point of the "Yield" paper, I think)

So then, my altered version of the zipper on Oleg's page, using `yield`

:

> import Data.Traversable as T > type Zipper t a = Iterator (Maybe a) a (t a) > make_zipper :: T.Traversable t => t a -> Zipper t a > make_zipper t = run $ T.mapM f t > where > f a = do > r <- yield a > return $ maybe a id r

This is run and yield pretty much as defined on page 10 of the yield paper:

> data Iterator i o r = Result r | Susp o (i -> Iterator i o r) > yield x = shift (\k -> return $ Susp x k) > run x = reset $ x >>= return . Result

and some test code:

> sample = [1,2,3] > main = do > let (Susp a1 k1) = make_zipper sample > print a1 > let (Susp a2 k2) = k1 Nothing > print a2 > let (Susp a3 k3) = k2 $ Just 100 > print a3 > let (Result end) = k3 Nothing > print end

and below, to make this posting properly executable, here's Oleg's library code for shift/reset:

> -- The Cont monad for delimited continuations, implemented here to avoid > -- importing conflicting monad transformer libraries > newtype Cont r a = Cont{runCont :: (a -> r) -> r} > instance Monad (Cont r) where > return x = Cont $ \k -> k x > m >>= f = Cont $ \k -> runCont m (\v -> runCont (f v) k) > reset :: Cont r r -> r > reset m = runCont m id > shift :: ((a -> r) -> Cont r r) -> Cont r a > shift e = Cont (\k -> reset (e k))

Update 1: Changed types from Oleg's Z | ZDone to the yield paper's Susp | Result

## No comments:

## Post a Comment