CC-delcont 0.1 → 0.2
raw patch · 6 files changed
+185/−23 lines, 6 files
Files
- CC-delcont.cabal +11/−5
- Control/Monad/CC.hs +26/−14
- Control/Monad/CC/Cursor.hs +144/−0
- Control/Monad/CC/Dynvar.hs +1/−1
- Control/Monad/CC/Prompt.hs +1/−1
- Control/Monad/CC/Seq.hs +2/−2
CC-delcont.cabal view
@@ -1,5 +1,5 @@ Name: CC-delcont-Version: 0.1+Version: 0.2 Description: An implementation of multi-prompt delimited continuations based on the paper, /A Monadic Framework for Delimited Continuations/, by R. Kent Dybvig, Simon Peyton Jones and Amr Sabry@@ -15,23 +15,29 @@ Category: Control License: OtherLicense License-File: LICENSE-Copyright: Copyright (c) 2005--2007, R. Kent Dybvig, Simon Peyton Jones,+Copyright: Copyright (c) 2005--2008, R. Kent Dybvig, Simon Peyton Jones, Amr Sabry, Oleg Kiselyov, Chung-chieh Shan Author: R. Kent Dybvig, Simon Peyton Jones, Amr Sabry, Oleg Kiselyov, Chung-chieh Shan Maintainer: dan.doel@gmail.com Homepage: http://code.haskell.org/~dolio/CC-delcont+ Stability: Experimental Tested-With: GHC Build-Depends: base, mtl+Build-Type: Simple+ Exposed-Modules: Control.Monad.CC, Control.Monad.CC.Dynvar, Control.Monad.CC.Seq,- Control.Monad.CC.Prompt+ Control.Monad.CC.Prompt,+ Control.Monad.CC.Cursor Extensions: MultiParamTypeClasses, UndecidableInstances, FunctionalDependencies, Rank2Types,- GeneralizedNewtypeDeriving-GHC-Options: -O2+ GeneralizedNewtypeDeriving,+ FlexibleInstances,+ GADTs+GHC-Options: -O2 -Wall
Control/Monad/CC.hs view
@@ -1,8 +1,5 @@-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE Rank2Types, GeneralizedNewtypeDeriving, MultiParamTypeClasses,+ UndecidableInstances, FunctionalDependencies, FlexibleInstances, GADTs #-} -------------------------------------------------------------------------- -- |@@ -41,10 +38,12 @@ shift0, control0, abort- -- * examples- -- $examples+ -- * Examples+ -- $Examples ) where +import Control.Applicative+ import Control.Monad.Identity import Control.Monad.State import Control.Monad.Reader@@ -53,7 +52,9 @@ import Control.Monad.CC.Seq import Control.Monad.CC.Prompt -newtype Frame m ans a b = Frame (a -> CCT ans m b)+-- newtype Frame m ans a b = Frame (a -> CCT ans m b)+data Frame m ans a b = FFrame (a -> b)+ | MFrame (a -> CCT ans m b) type Cont ans m a = Seq (Frame m) ans a newtype SubCont ans m a b = SC (SubSeq (Frame m) ans a b)@@ -73,9 +74,16 @@ -- type 'a' newtype CCT ans m a = CCT { unCCT :: Cont ans m a -> P ans m ans } +instance (Monad m) => Functor (CCT ans m) where+ fmap f (CCT e) = CCT $ \k -> e (PushSeg (FFrame f) k)++instance (Monad m) => Applicative (CCT ans m) where+ pure = return+ (<*>) = ap+ instance (Monad m) => Monad (CCT ans m) where return v = CCT $ \k -> appk k v- (CCT e1) >>= e2 = CCT $ \k -> e1 (PushSeg (Frame e2) k)+ (CCT e1) >>= e2 = CCT $ \k -> e1 (PushSeg (MFrame e2) k) instance MonadTrans (CCT ans) where lift m = CCT $ \k -> lift m >>= appk k@@ -93,9 +101,12 @@ -- Applies a continuation to a value. appk :: Monad m => Cont ans m a -> a -> P ans m ans-appk EmptyS a = return a-appk (PushP _ k) a = appk k a-appk (PushSeg (Frame f) k) a = unCCT (f a) k+appk EmptyS a = return a+appk (PushP _ k) a = appk k a+appk (PushSeg f k) a = appFrame f a k+ where+ appFrame (MFrame g) b l = unCCT (g b) l+ appFrame (FFrame g) b l = appk l (g b) -- | Executes a CCT computation, yielding a value in the underlying monad runCCT :: (Monad m) => (forall ans. CCT ans m a) -> m a@@ -103,7 +114,8 @@ -- | The CC monad may be used to execute computations with delimited control. newtype CC ans a = CC { unCC :: CCT ans Identity a }- deriving (Monad, MonadDelimitedCont (Prompt ans) (SubCont ans Identity))+ deriving (Functor, Monad, Applicative, + MonadDelimitedCont (Prompt ans) (SubCont ans Identity)) -- | Executes a CC computation, yielding a resulting value. runCC :: (forall ans. CC ans a) -> a@@ -198,7 +210,7 @@ abort p e = withSubCont p (\_ -> e) ---------------------------------------------------------------------------------- $examples+-- $Examples -- -- This module provides many different control operators, so hopefully the -- examples herein can help in selecting the right ones. The most raw are the
+ Control/Monad/CC/Cursor.hs view
@@ -0,0 +1,144 @@+{-# LANGUAGE GADTs, MultiParamTypeClasses, FunctionalDependencies #-}++-------------------------------------------------------------------------------+-- |+-- Module : Control.Monad.CC.Cursor+-- Copyright : (c) Dan Doel+-- License : MIT+--+-- Maintainer : Dan Doel+-- Stability : Experimental+-- Portability : Non-portable (Generalized algebraic data types,+-- Functional Dependencies)+--+-- Implements various cursor datatypes for iterating over collections+module Control.Monad.CC.Cursor (+ Cursor(..),+ Iterator,+ generator,+ iterator,+ current,+ next,+ open,+ update,+-- Walkable(..),+-- Zipper,+-- zipper,+-- previousDir,+-- currentTerm,+-- move+ ) where++import Prelude hiding (zip, mapM, mapM_)+import Control.Monad hiding (mapM, mapM_)+import Control.Monad.CC++import Data.Maybe+import Data.Foldable+import Data.Traversable hiding (traverse)++-- | A generalized type that represents a reified data structure traversal.+-- The other traversal data types in this module are special cases of this+-- general type. Cursor is parameterized by four types:+--+-- m : The monad in which the Cursor object is usable.+--+-- r : The result type, which will be stored in the cursor once the traversal+-- has been completed.+--+-- b : The type that the cursor expects to receive before moving on to the+-- next element in the traversal.+--+-- a : The element type to which the Cursor provides access at each step in+-- the traversal.+data Cursor m r b a where+ Current :: Monad m => a -> (b -> m (Cursor m r b a)) -> Cursor m r b a+ Done :: Monad m => r -> Cursor m r b a++-- | A simple iterator, which provides a way to view each of the elements of+-- a data structure in order.+type Iterator m a = Cursor m () () a++-- | A function for making a cursor out of a free form generator, similar to+-- using 'yield' in Ruby or Python. For example:+--+-- > generator $ \yield -> do a <- yield 1 ; yield 2 ; b <- yield 3 ; return [a,b]+generator :: MonadDelimitedCont p s m => ((a -> m b) -> m r) -> m (Cursor m r b a)+generator f = reset (\p -> Done `liftM` f (yield p))+ where yield p a = shift p (\k -> return $ Current a (k . return))++-- A general cursor builder; takes the traversal function, a data structure, and+-- returns a corresponding cursor. Currently not exported, just used internally.+makeCursor :: (MonadDelimitedCont p s m) =>+ ((a -> m b) -> t -> m r) -> t -> m (Cursor m r b a)+makeCursor iter t = generator $ flip iter t++-- | Creates an Iterator that will yield each of the elements of a Foldable in+-- order.+iterator :: (Foldable t, MonadDelimitedCont p s m) => t a -> m (Iterator m a)+iterator = makeCursor mapM_++-- | Advances an Iterator to the next element (has no effect on a finished Iterator).+next :: Iterator m a -> m (Iterator m a)+next = update ()++-- | Extracts the current element from a cursor, if applicable.+current :: Cursor m r b a -> Maybe a+current (Done _) = Nothing+current (Current a _) = Just a++-- | Begins an updating traversal over a Traversable structure. At each step,+-- the cursor will hold an element of type a, and providing an element of type+-- b will move on to the next step. When done, a new Traversable object holding+-- elements of type b will be available.+open :: (Traversable t, MonadDelimitedCont p s m) => t a -> m (Cursor m (t b) b a)+open = makeCursor mapM++-- | Provides an item to a Cursor, moving on to the next step in the traversal.+-- (has no effect on a finished Cursor).+update :: b -> Cursor m r b a -> m (Cursor m r b a)+update _ c@(Done _) = return c+update b (Current _ k) = k b++-- Removing for now. This isn't remotely done, and I need to reread ccshan's+-- stuff on zippers and such before I can begin to get it right.+{-+class Direction d where+ nextD :: d -> d++class Direction d => Walkable t d | t -> d where+ walk :: Monad m => (d -> t -> m (Maybe t, d)) -> t -> m t++data ListDir = LLeft | LRight++instance Direction ListDir where+ nextD = id++instance Walkable [a] ListDir where+ walk tr ll = fromMaybe ll `liftM` traverse LRight ll+ where+ traverse d l = do (ml, d') <- tr d l+ let l' = fromMaybe l ml+ maybe ml Just `liftM` select l' d'+ select _ LLeft = return Nothing+ select l@(x:xs) LRight = do l' <- liftM (x:) `liftM` traverse LRight xs+ maybe l' Just `liftM` traverse LLeft (fromMaybe l l')+ select [] LRight = maybe Nothing Just `liftM` traverse LLeft []++type Zipper m t d = Cursor m t (Maybe t, d) (d,t)++zipper :: (MonadDelimitedCont p s m, Walkable t d) => t -> m (Zipper m t d)+zipper = makeCursor $ walk . curry++previousDir :: Zipper m t d -> Maybe d+previousDir (Done _) = Nothing+previousDir (Current (d,_) _) = Just d++currentTerm :: Zipper m t d -> t+currentTerm (Done t) = t+currentTerm (Current (_,t) _) = t++move :: d -> Zipper m t d -> m (Zipper m t d)+move _ z@(Done _) = return z+move d (Current _ k) = k (Nothing, d)+-}
Control/Monad/CC/Dynvar.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-}+{-# LANGUAGE GADTs #-} ------------------------------------------------------------------------------- -- |
Control/Monad/CC/Prompt.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-}+{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving #-} ------------------------------------------------------------------------------- -- |
Control/Monad/CC/Seq.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -fglasgow-exts #-}+{-# LANGUAGE GADTs #-} ------------------------------------------------------------------------------- -- |@@ -64,7 +64,7 @@ -- | Splits a sequence at the given prompt into a sub-sequence, and -- the rest of the sequence splitSeq :: Prompt ans b -> Seq seg ans a -> (SubSeq seg ans a b, Seq seg ans b)-splitSeq p EmptyS = error "Prompt was not found on the stack."+splitSeq _ EmptyS = error "Prompt was not found on the stack." splitSeq p (PushP p' sk) = case eqPrompt p' p of EQU -> (emptySubSeq, sk)