packages feed

oi 0.0.5 → 0.1.0

raw patch · 12 files changed

+687/−315 lines, 12 filesdep +filepathdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: filepath

Dependency ranges changed: base

API changes (from Hackage documentation)

- Data.OI: (#) :: a -> OI a
- Data.OI: (<.>) :: (b :-> c) -> (a :-> b) -> (a :-> c)
- Data.OI: (<|) :: (b -> c) -> (a :-> b) -> (a :-> c)
- Data.OI: (=:) :: a -> a :-> a
- Data.OI: (>|->|) :: (a -> b :-> c) -> (a' -> b' :-> c') -> ((a, a') -> (b, b') :-> (c, c'))
- Data.OI: (>|>|) :: (a -> b :-> c) -> (c -> d :-> e) -> (a -> (b, d) :-> e)
- Data.OI: (?) :: a :-> a
- Data.OI: (|-|) :: (a :-> b) -> (a' :-> b') -> (a, a') :-> (b, b')
- Data.OI: (|<|) :: (b -> c :-> d) -> (a :-> b) -> (a, c) :-> d
- Data.OI: (|<|<) :: (c -> d :-> e) -> (a -> b :-> c) -> (a -> (b, d) :-> e)
- Data.OI: (|>) :: (a :-> b) -> (b -> c) -> (a :-> c)
- Data.OI: (|><|) :: (q -> a :-> (p, c)) -> (p -> b :-> (q, d)) -> ((a, b) :-> (c, d))
- Data.OI: (|>|) :: (a :-> b) -> (b -> c :-> d) -> (a, c) :-> d
- Data.OI: arrA :: (a -> b) -> (a :-> b)
- Data.OI: data OI a
- Data.OI: deList :: [a] :-> Maybe (OI a, OI [a])
- Data.OI: deTriple :: (a, b, c) :-> (OI a, OI b, OI c)
- Data.OI: deTuple :: OI (a, b) -> (OI a, OI b)
- Data.OI: firstA :: (a :-> b) -> (a, c) :-> (b, c)
- Data.OI: idA :: a :-> a
- Data.OI: instance Applicative OI
- Data.OI: instance Comonad OI
- Data.OI: instance Extend OI
- Data.OI: instance Functor OI
- Data.OI: instance Monad OI
- Data.OI: iooi :: IO a -> (a :-> a)
- Data.OI: mapOI :: (a :-> b) -> [a] :-> [b]
- Data.OI: mapOI' :: (a :-> b) -> [a] :-> (OI [a], [b])
- Data.OI: mergeOI :: [a] -> [a] -> [a] :-> [a]
- Data.OI: run :: (a :-> b) -> IO b
- Data.OI: sequenceOI :: [a :-> b] -> [a] :-> ()
- Data.OI: sequenceOI' :: [a :-> b] -> [a] :-> OI [a]
- Data.OI: type :-> a b = OI a -> b
- Data.OI: zipWithOI :: (a -> b :-> c) -> [a] -> [b] :-> [c]
- Data.OI: zipWithOI' :: (a -> b :-> c) -> [a] -> [b] :-> (OI [b], [c])
+ Data.OI.Base: (=:) :: a -> OI a -> a
+ Data.OI.Base: (??) :: OI a -> a
+ Data.OI.Base: Failure :: String -> IOResult a
+ Data.OI.Base: Success :: a -> IOResult a
+ Data.OI.Base: data IOResult a
+ Data.OI.Base: data OI a
+ Data.OI.Base: deLeft :: OI (Either a b) -> Either (OI a) (OI b)
+ Data.OI.Base: deList :: OI [a] -> Maybe (OI a, OI [a])
+ Data.OI.Base: dePair :: OI (a, b) -> (OI a, OI b)
+ Data.OI.Base: deRight :: OI (Either a b) -> Either (OI a) (OI b)
+ Data.OI.Base: deTriple :: OI (a, b, c) -> (OI a, OI b, OI c)
+ Data.OI.Base: deTuple4 :: OI (a, b, c, d) -> (OI a, OI b, OI c, OI d)
+ Data.OI.Base: deTuple5 :: OI (a, b, c, d, e) -> (OI a, OI b, OI c, OI d, OI e)
+ Data.OI.Base: deTuple6 :: OI (a, b, c, d, e, f) -> (OI a, OI b, OI c, OI d, OI e, OI f)
+ Data.OI.Base: deTuple7 :: OI (a, b, c, d, e, f, g) -> (OI a, OI b, OI c, OI d, OI e, OI f, OI g)
+ Data.OI.Base: force :: a -> ()
+ Data.OI.Base: forces :: [()] -> ()
+ Data.OI.Base: instance Comonad OI
+ Data.OI.Base: instance Extend OI
+ Data.OI.Base: instance Functor IOResult
+ Data.OI.Base: instance Functor OI
+ Data.OI.Base: instance Monad OI
+ Data.OI.Base: instance Show a => Show (IOResult a)
+ Data.OI.Base: iooi :: IO a -> OI a -> a
+ Data.OI.Base: iooi' :: IO a -> OI (IOResult a) -> IOResult a
+ Data.OI.Base: run :: (OI a -> b) -> IO b
+ Data.OI.Base: split :: a -> (a, ())
+ Data.OI.Base: type :-> a b = OI a -> b
+ Data.OI.Combinator: (|/|) :: (a :-> c) -> (c -> (b :-> d)) -> ((a, b) :-> d)
+ Data.OI.Combinator: (|:|) :: (a :-> c) -> (b :-> d) -> ((a, b) :-> (c, d))
+ Data.OI.Combinator: (|>) :: (a -> b) -> (b -> c) -> (a -> c)
+ Data.OI.Combinator: (|><|) :: (a :-> (p -> (q, c))) -> (b :-> (q -> (p, d))) -> ((a, b) :-> (c, d))
+ Data.OI.Combinator: (|>|) :: (a :-> (p, c)) -> (b :-> (p -> d)) -> ((a, b) :-> (c, d))
+ Data.OI.Combinator: choice :: a -> a -> Bool -> a
+ Data.OI.Combinator: choiceOI :: (a :-> c) -> (b :-> c) -> Bool -> (Either a b :-> c)
+ Data.OI.Combinator: ifOI :: Bool -> (a :-> c) -> (b :-> c) -> (Either a b :-> c)
+ Data.OI.Combinator: mapOI :: (a :-> b) -> ([a] :-> [b])
+ Data.OI.Combinator: seqsOI :: [a] :-> ([a :-> b] -> ())
+ Data.OI.Combinator: seqsOI' :: [a :-> b] -> ([a] :-> ())
+ Data.OI.Combinator: zipWithOI :: (a :-> (b -> c)) -> ([a] :-> ([b] -> [c]))
+ Data.OI.Combinator: zipWithOI' :: (a -> (b :-> c)) -> ([a] -> ([b] :-> [c]))
+ Data.OI.IO: getLine :: String :=> String
+ Data.OI.IO: hClose :: Handle -> () :=> ()
+ Data.OI.IO: hGetLine :: Handle -> String :=> String
+ Data.OI.IO: hIsClosed :: Handle -> Bool :=> Bool
+ Data.OI.IO: hIsEOF :: Handle -> Bool :=> Bool
+ Data.OI.IO: hPutStrLn :: Handle -> String -> () :=> ()
+ Data.OI.IO: isEOF :: Bool :=> Bool
+ Data.OI.IO: openFile :: FilePath -> IOMode -> Handle :=> Handle
+ Data.OI.IO: putStrLn :: String -> () :=> ()
+ Data.OI.Resource: Resource :: () -> [IOResult a] -> Resource a
+ Data.OI.Resource: data Resource a
+ Data.OI.Resource: filterR :: (a -> Bool) -> IOResult (Resource a) -> [a]
+ Data.OI.Resource: inFileResource :: FilePath -> IOResult (Resource String) :-> IOResult (Resource String)
+ Data.OI.Resource: instance Show a => Show (Resource a)
+ Data.OI.Resource: mapR :: (a -> b) -> IOResult (Resource a) -> [b]
+ Data.OI.Resource: mapR' :: (a -> b) -> Resource a -> [b]
+ Data.OI.Resource: outFileResource :: FilePath -> [String] -> IOResult (Resource ()) :-> IOResult (Resource ())
+ Data.OI.Resource: release :: Resource a -> ()
+ Data.OI.Resource: stream :: Resource a -> [IOResult a]
+ Data.OI.Resource: takeR :: Integral i => i -> IOResult (Resource a) -> [a]
+ Data.OI.Resource: takeR' :: Integral i => i -> Resource a -> [a]
+ Data.OI.Resource: takeWhileR :: (a -> Bool) -> IOResult (Resource a) -> [a]
+ Data.OI.System: args :: [String] :-> [String]
+ Data.OI.System: environment :: [(String, String)] :-> [(String, String)]
+ Data.OI.System: progName :: String :-> String

Files

oi.cabal view
@@ -1,23 +1,29 @@ Name:			oi-Version:		0.0.5+Version:		0.1.0 Category:		Data Synopsis:		Purely Functional Lazy Interaction with the outer world Description:		This package implements a data structure and operations on it  			for making interactive program without using explicitly IO monads.+			Version 0.1.0: APIs are changed from before. Stability:		Experimental License:		BSD3 License-File:		LICENSE Author:			Nobuo Yamashita Maintainer:		nobsun@sampou.org Build-Type:		Simple-Cabal-Version:		>= 1.6+Cabal-Version:		>= 1.14  Data-dir:		sample-Data-files:		Makefile echo.hs recdircs.hs talk.hs+Data-files:		Makefile cats.hs echo.hs recdircs.hs talk.hs  Library+  Default-Language:         Haskell2010   Hs-Source-Dirs:	    src/-  Build-Depends:	    base >= 4 && < 5, parallel, comonad+  Build-Depends:	    base >= 4.5 && < 5, parallel, comonad, filepath   GHC-Options:		    -Wall -O0   Exposed-modules:	    Data.OI-+                           ,Data.OI.Base+                           ,Data.OI.Combinator+                           ,Data.OI.IO+                           ,Data.OI.Resource+                           ,Data.OI.System
sample/Makefile view
@@ -1,4 +1,4 @@-EXECS = echo recdircs talk+EXECS = echo recdircs talk cats  all	: $(EXECS) @@ -9,6 +9,9 @@ 	ghc --make -O0 -threaded $< -o $@  talk	: talk.hs+	ghc --make -O0 -threaded $< -o $@++cats	: cats.hs 	ghc --make -O0 -threaded $< -o $@  clean	:
+ sample/cats.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE BangPatterns+            ,TypeOperators+  #-}+module Main where++import Data.List+import Data.OI+import Prelude as P++main :: IO ()+main = run pmain'++pmain :: (IOResult (Resource String), ([IOResult (Resource String)], [()])) :-> ()+pmain = forces . (mapR id . inFileResource "files" |/| head3s)++head3s :: [FilePath] -> ([IOResult (Resource String)], [()]) :-> [()]+head3s xs = map (unlines . takeR (3::Int)) . zipWithOI' inFileResource xs |/| zipWithOI' (iooi . P.putStrLn)++pmain' :: (IOResult (Resource String), ([IOResult (Resource String)], IOResult (Resource ()))) :-> ()+pmain' = mapR id . inFileResource "files" |/| head3s'++head3s' :: [FilePath] -> ([IOResult (Resource String)], IOResult (Resource ())) :-> ()+head3s' xs = forceResult . (map (unlines . ("==========":) . takeR (3::Int)) . zipWithOI' inFileResource xs |/| outFileResource "/dev/pts/3")++forceResult :: IOResult (Resource a) -> ()+forceResult (Success s) = forces $ map force $ stream s+forceResult (Failure e) = error e++main' :: IO ()+main' = readFile "files"+    >>= mapM readFile . lines >>= mapM_  putStr . intersperse "==========" . map (unlines . take 3 . lines)
sample/echo.hs view
@@ -1,15 +1,17 @@-{-# LANGUAGE TypeOperators-  #-}+{-# LANGUAGE TypeOperators #-} module Main where -import Data.OI+import Data.OI hiding (isEOF)  import Data.Char import System.IO  main :: IO ()-main = do { [] <- run $ puts |<| gets; return () }+main = run $ pmain1 +pmain0 = forces . mapOI echo+pmain1 = forces . echos+ eof :: Int eof = -1 @@ -19,18 +21,21 @@ putc :: Char -> () :-> () putc = iooi . putChar +putc' :: Int -> () :-> ()+putc' (-1) = const ()+putc' c    = iooi (putChar (chr c))  gets :: [Int] :-> String gets = map chr . takeWhile (eof /=) . mapOI getc  puts :: String -> [()] :-> [()]-puts s = dropWhile (()==) . snd . zipWithOI' putc s--choice :: a -> a -> Bool -> a-choice t f c = if c then t else f+puts = zipWithOI' putc  getchar :: IO Int getchar = choice (return (-1)) (return . ord =<< getChar) =<< isEOF  -puts' :: String -> [()] :-> ()-puts' = sequenceOI . map putc+puts' :: String -> OI [()] -> ()+puts' = seqsOI' . map putc++echo  = getc |/| putc'+echos = gets |/| puts
sample/recdircs.hs view
@@ -1,45 +1,43 @@-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TupleSections  +            ,PostfixOperators+            ,TypeOperators+            #-} module Main where -import Data.OI-+import Control.Arrow import Data.List-+import Data.OI import System.FilePath import System.Directory-import System.Environment  main :: IO ()-main = do { args <- getArgs-          ; case args of-              []  -> print =<< run (pmain ".")-              a:_ -> print =<< run (pmain a)-          }+main = run pmain -pmain :: FilePath -> [(Bool, [FilePath])] :-> [FilePath]-pmain = recDirectoryContents+pmain :: (([String], [(Bool, IOResult [FilePath])]), ()) :-> ()+pmain = ((args |> head) |/| getDirCsRec) |> snd |/| putStrOI . unlines +putStrOI :: String -> () :-> ()+putStrOI = iooi . putStr+ isDirectory :: FilePath -> Bool :-> Bool isDirectory = iooi . doesDirectoryExist -directoryContents :: FilePath -> [FilePath] :-> [FilePath]-directoryContents f = map (f </>) . filter (`notElem` [".",".."])-                    . iooi (getDirectoryContents f)+getDirCs' :: FilePath -> IOResult [FilePath] :-> [FilePath]+getDirCs' fp = iooi'  (getDirectoryContents fp) |> valid -recDirectoryContents :: FilePath -> [(Bool,[FilePath])] :-> [FilePath]-recDirectoryContents root = fst . recdircs root+valid :: IOResult [FilePath] -> [FilePath]+valid (Success fps) = filter (flip notElem [".",".."]) fps+valid _             = [] -recdircs :: FilePath -> [(Bool,[FilePath])] :-> ([FilePath], OI [(Bool,[FilePath])])-recdircs t r = case deList r of-  Just (rbfps, rbfpss) -> case deTuple rbfps of-    (rb,rfps) -> case isDirectory t rb of-      False -> ([t],rbfpss)-      True  -> let { ts = directoryContents t rfps-                   ; (rs,tss) = mapAccumL acc rbfpss ts-                   ; acc r' fp = swap (recdircs fp r')-                   } in -               (concat tss, rs)-  _ -> error $ "recdircs: perhaps `"++t++"' is not found"+getDirCs :: FilePath -> (Bool, IOResult [FilePath]) :-> (Bool, [FilePath])+getDirCs fp = isDirectory fp+          |/| choice (((,) True) . map (fp </>) . getDirCs' fp) (const (False, [fp])) -swap :: (a,b) -> (b,a)-swap (x,y) = (y,x)+getDirCsRec ::  FilePath+            ->  [(Bool, IOResult [FilePath])]+            :-> (OI [(Bool, IOResult [FilePath])], [FilePath])+getDirCsRec fp oss = case deList oss of+  Just (o,os) -> case getDirCs fp o of+    (False, fps) -> (os,fps)+    (True,  fps) -> second concat $ mapAccumL (flip getDirCsRec) os fps+  _           -> error $ "getDirCs: perhaps `"++ fp ++"' is not found"
sample/talk.hs view
@@ -3,6 +3,8 @@ module Main where  import Data.OI++import Control.Concurrent import Control.Parallel import System.Environment @@ -13,23 +15,23 @@  pmain ::  (FilePath,FilePath)       ->  (FilePath,FilePath)-      ->  ((String, [String], ()), (String, [String], ()))-      :-> ()-pmain (kbd1,scr1) (kbd2,scr2)-  = uncurry par . (talk "Alice" (kbd1,scr1) |><| talk "Bob" (kbd2,scr2))+      ->  ((String, [String], ()), (String, [String], ())) :-> ()+pmain devs1 devs2 = uncurry par . (talk "Alice" devs1 |><| talk "Bob" devs2) -talk :: String                   -- Talker's name-     -> (FilePath,FilePath)      -- (Talker's keybord, Talker's screen)-     -> [String]                 -- Messages from the other end-     -> OI (String,[String],())  -- (Talker's input,Merged messages, Process result)-     -> ([String],())            -- (Messages to the other end, Process result)-talk name (kbd,scr) msg r = (ins,showscr scr (mergeOI ins msg os) us)+talk :: String                -- Talker's name+     -> (FilePath,FilePath)   -- (Talker's keybord, Talker's screen)+     -> (String,[String],())  -- (Talker's input,Merged messages, Process result)+    :-> [String]             -- Messages from the other end+     -> ([String],())        -- (Messages to the other end, Process result)+talk name (kbd,scr) r msg = (ins,showscr scr (mergeOI ins msg os) us)   where     (is,os,us) = deTriple r     ins = map ((name ++ ": ")++) $ lines $ readkbd kbd is -readkbd :: FilePath -> String :-> String+readkbd :: FilePath -> OI String -> String readkbd = iooi . readFile -showscr :: FilePath -> [String] -> () :-> ()+showscr :: FilePath -> [String] -> OI () -> () showscr s = iooi . writeFile s . unlines++mergeOI = (iooi .) . mergeIO
src/Data/OI.hs view
@@ -1,265 +1,23 @@-{-# LANGUAGE TypeOperators-            ,ScopedTypeVariables-            ,PostfixOperators-            ,NoMonomorphismRestriction-            ,BangPatterns-  #-}-{-# OPTIONS_GHC -fno-cse #-} -- | -- Module      : Data.OI--- Copyright   : (c) Nobuo Yamashita 2011+-- Copyright   : (c) Nobuo Yamashita 2011-2012 -- License     : BSD3 -- Author      : Nobuo Yamashita -- Maintainer  : nobsun@sampou.org -- Stability   : experimental ----- Comonadic data type for representing interaction with outer world.----module Data.OI (-  -- * Data type-  OI- ,(:->)--  -- * Converter an IO to an interaction function- ,iooi--  -- * Drive an interaction function- ,run--  -- * Primitive operators on the interaction data- ,(=:)- ,(?)- ,(#)--  -- * Category class methods on (:->)- ,idA- ,(<.>)--  -- * Arrow class methods on (:->)- ,arrA- ,firstA--  -- * Embeding interaction data in data structure- ,deTuple- ,deTriple- ,deList--  -- * Interaction combinators- ,(>|>|)- ,(|<|<)- ,(>|->|)- ,(|-|)- ,(|<|)- ,(|>|)- ,(<|)- ,(|>)- ,(|><|)- ,mapOI- ,mapOI'- ,zipWithOI- ,zipWithOI'- ,sequenceOI- ,sequenceOI'- ,mergeOI-- ) where--import Control.Applicative-import Control.Concurrent-import Control.Parallel-import Control.Comonad-import System.IO.Unsafe--data OI a = OI { variable :: LeftValueOf (IO a), value :: a }-type a :-> b = OI a -> b---- | Binding operator-(=:)         ::  a -> a :-> a-x =: OI v y  =   assign ix v `pseq` y-                 where ix = return x---- | Dereference operator-(?)           ::  a :-> a-(?) (OI _ x)  =   x---- | Reference operator-(#)    ::  a -> OI a-(#) x  =   OI { variable = reference (return x), value = x }------instance Functor OI where-  fmap f = (#) . f . (?)--instance Monad OI where-  return = (#)-  x >>= f = f (x?)--instance Applicative OI where-  pure  = (#)-  (<*>) = (. (?)) . ((#) .) . (?)--instance Extend OI where-  duplicate = (#)--instance Comonad OI where-  extract = (?)------idA :: a :-> a-idA = (?)--(<.>) :: (b :-> c) -> (a :-> b) -> (a :-> c)-f <.> g = f . (#) . g------arrA :: (a -> b) -> (a :-> b)-arrA f = f . (?)--firstA :: (a :-> b) -> (a,c) :-> (b,c)-firstA f ac = case deTuple ac of (x,z) -> (f x, (z?))---- | Embed interactions into tuple-deTuple :: OI (a,b) -> (OI a,OI b)-deTuple (OI vxy ~(x,y)) = assign io vxy `pseq` (OI vx x, OI vy y)- where-  vx     = new0 ()-  vy     = new0 ()-  io     = (,) <$> unsafeInterleaveIO (dereference vx) <*> unsafeInterleaveIO (dereference vy)---- | Embed interactions into triple-deTriple :: (a,b,c) :-> (OI a,OI b,OI c)-deTriple (OI vxyz ~(x,y,z)) = assign io vxyz `pseq` (OI vx x, OI vy y, OI vz z)- where-  vx     = new0 ()-  vy     = new0 ()-  vz     = new0 ()-  io     = (,,) <$> unsafeInterleaveIO (dereference vx)-                <*> unsafeInterleaveIO (dereference vy)-                <*> unsafeInterleaveIO (dereference vz)---- | Embed interactions into list-deList :: [a] :-> Maybe (OI a, OI [a])-deList (OI vxxs xxs)- = assign io vxxs-   `pseq` case xxs of-      x:xs -> Just (OI vx x, OI vxs xs)-      _    -> Nothing-   where-     vx  = new0 ()-     vxs = new0 ()-     io  = (:) <$> (unsafeInterleaveIO (dereference vx)) <*> (unsafeInterleaveIO (dereference vxs))---- | Connect two interactions into an interaction--(|<|<) :: (c -> d :-> e) -> (a -> b :-> c) -> (a -> (b,d) :-> e)-(f |<|< g) a bd = case deTuple bd of (b,d) -> f (g a b) d--(>|>|) :: (a -> b :-> c) -> (c -> d :-> e) -> (a -> (b,d) :-> e)-(>|>|) = flip (|<|<)--(>|->|) :: (a -> b :-> c) -> (a' -> b' :-> c') -> ((a,a') -> (b,b') :-> (c,c'))-(f >|->| g) (a,a') bb' = case deTuple bb' of (b,b') -> (f a b, g a' b')--(|-|) :: (a :-> b) -> (a' :-> b') -> (a,a') :-> (b,b')-(f |-| g) aa' = case deTuple aa' of (a,a') -> (f a, g a')--(|<|)  ::  (b -> c :-> d) -> (a :-> b) -> (a,c) :-> d-(f |<| g) ac = case deTuple ac of (a,c) -> f (g a) c--(|>|)  :: (a :-> b) -> (b -> c :-> d) -> (a,c) :-> d-(|>|) = flip (|<|)--infixr 1 |<|-infixl 1 |>|--(|>) :: (a :-> b) -> (b -> c) -> (a :-> c)-(|>) = flip (.)--(<|) :: (b -> c) -> (a :-> b) -> (a :-> c)-(<|) = (.)--(|><|) :: (q -> a :-> (p,c)) -> (p -> b :-> (q,d)) -> ((a,b)  :-> (c,d))-(f |><| g) rab = case deTuple rab of-  (ra,rb) -> (c,d)-   where -     (x,c) = f y ra-     (y,d) = g x rb----- | Map interaction function on an interaction list-mapOI :: (a :-> b) -> [a] :-> [b]-mapOI f xxs = case deList xxs of-  Just (x,xs) -> f x : mapOI f xs-  _           -> []---- | Map interaction function on an interaction list (return results and remainings)-mapOI' :: (a :-> b) -> [a] :-> (OI [a],[b])-mapOI' f xxs = case deList xxs of-  Just (x,xs) -> (zs, f x:ys)-                 where (zs,ys) = mapOI' f xs-  _           -> (xxs,[])---- | Zip a list and an interaction list-zipWithOI :: (a -> b :-> c) -> [a] -> [b] :-> [c]-zipWithOI _ [] _  = []-zipWithOI f (x:xs) yys = case deList yys of-  Just (y,ys) -> f x y : zipWithOI f xs ys-  _           -> []---- | Zip a list and an interaction list (return results and remainings)-zipWithOI' :: (a -> b :-> c) -> [a] -> [b] :-> (OI [b],[c])-zipWithOI' _ []     yys = (yys,[])-zipWithOI' f (x:xs) yys = case deList yys of-  Just (y,ys) -> case zipWithOI' f xs ys of ~(rs,zs) -> (rs,f x y : zs)-  _           -> (yys,[])---- | Sequencing interaction functions-sequenceOI :: [a :-> b] -> [a] :-> ()-sequenceOI (f:fs) xxs = case deList xxs of-  Just (x,xs) -> f x `pseq` sequenceOI fs xs-  Nothing     ->  ()-sequenceOI [] _ = ()---- | Sequencing interaction functions (return remainings)-sequenceOI' :: [a :-> b] -> [a] :-> OI [a]-sequenceOI' (f:fs) xxs = case deList xxs of-  Just (x,xs) -> f x `pseq` sequenceOI' fs xs-  Nothing     ->  xxs-sequenceOI' [] xxs = xxs---- | Merging two lists by using oracles-mergeOI :: [a] -> [a] -> [a] :-> [a]-mergeOI xs ys = iooi $ mergeIO xs ys---- | Convert an IO to an interaction function-iooi            ::  IO a -> (a :-> a)-iooi io (OI vix x)  =   assign io vix `pseq` x---- | Drive an interaction function-run        ::  (a :-> b) -> IO b-run pmain  =   do { vx <- newEmptyMVar-                  ; x  <- unsafeInterleaveIO (dereference vx)-                  ; return $! pmain (OI vx x)-                  }---- --type LeftValueOf = MVar--new0 :: () -> LeftValueOf a-new0 () = unsafePerformIO $ newEmptyMVar--reference :: a -> LeftValueOf a-reference = unsafePerformIO . newMVar--dereference :: LeftValueOf a -> a-dereference = unsafePerformIO . readMVar+module Data.OI +  (+  -- * Export modules+   module Data.OI.Base+  ,module Data.OI.Combinator+  ,module Data.OI.IO+  ,module Data.OI.Resource+  ,module Data.OI.System+  ) where -assign :: a -> LeftValueOf a -> a-assign !x v = unsafePerformIO -            $ do { s <- tryPutMVar v x-                 ; if s then return x else readMVar v-                 }+import Data.OI.Base+import Data.OI.Combinator+import Data.OI.IO+import Data.OI.Resource+import Data.OI.System
+ src/Data/OI/Base.hs view
@@ -0,0 +1,276 @@+{-# LANGUAGE TypeOperators+            ,ScopedTypeVariables+            ,PostfixOperators+            ,NoMonomorphismRestriction+            ,BangPatterns+  #-}+{-# OPTIONS_GHC -fno-cse #-}+-- |+-- Module      : Data.OI.Base+-- Copyright   : (c) Nobuo Yamashita 2011-2012+-- License     : BSD3+-- Author      : Nobuo Yamashita+-- Maintainer  : nobsun@sampou.org+-- Stability   : experimental+--+module Data.OI.Base+  (+  -- * Interaction datatypes+   OI+  ,(:->)+  -- * Drive an interaction+  ,run+  -- * Primitive operators on OI+  ,(=:)+  ,(??)+  -- * Splitter against OI+  ,dePair+  ,deList+  ,deTriple+  ,deTuple4+  ,deTuple5+  ,deTuple6+  ,deTuple7+  ,deLeft+  ,deRight+  -- * Convert IO to interaction+  ,IOResult(..)+  ,iooi+  ,iooi'+   -- * Forcing+  ,forces+  ,force+  ,split+  )+  where++import Control.Applicative+import Control.Category+import Control.Comonad+import Control.Exception+import Control.Monad+import Control.Concurrent+import Control.Parallel+import System.IO.Unsafe+import Prelude hiding ((.),id,catch)++-- | Datatype for intermediating interaction+data OI a = OI (LeftValueOf a) (RightValueOf a)++-- | Interaction type+type a :-> b = OI a -> b+infixr 0 :->++instance Functor OI where+  fmap f = (##) . f . (??)++instance Monad OI where+  return = (##)+  (>>=)  = flip ($) . (??)++instance Extend OI where+  duplicate = (##)++instance Comonad OI where+  extract = (??)++-- | Assign operator+(=:) :: a -> OI a -> a+(=:) !x (OI var val) = put (return x) var `pseq` val++-- | Dereference operator+(??) :: OI a -> a+(??) (OI _ val) = val++-- | Reference operator+(##) :: a -> OI a+(##) x = OI (unsafeNew x) x+++-- | Decomposer for pair+dePair :: OI (a,b) -> (OI a, OI b)+dePair (OI vxy ~(x,y)) = put io vxy `pseq` (OI vx x, OI vy y)+  where+    vx  = new x+    vy  = new y+    io  = (,) <$> lazy (deref vx) <*> lazy (deref vy)++-- | Decomposer for list+deList :: OI [a] -> Maybe (OI a, OI [a])+deList (OI vxxs xxs) = put io vxxs+  `pseq` case xxs of+     x:xs -> Just (OI vx x, OI vxs xs)+     _    -> Nothing+  where+    vx  = new (undefined :: a)+    vxs = new (undefined :: [a])+    io = (:) <$> lazy (deref vx) <*> lazy (deref vxs)++-- | Decomposer for triple+deTriple :: OI (a,b,c) -> (OI a, OI b, OI c)+deTriple (OI vxyz ~(x,y,z)) = put io vxyz+  `pseq` (OI vx x, OI vy y, OI vz z)+  where+    vx  = new x+    vy  = new y+    vz  = new z+    io  = (,,) <$> lazy (deref vx) +               <*> lazy (deref vy)+               <*> lazy (deref vz)++-- | Decomposer for 4-tuple+deTuple4 :: OI (a,b,c,d) -> (OI a, OI b, OI c, OI d)+deTuple4 (OI vwxyz ~(w,x,y,z)) = put io vwxyz+  `pseq` (OI vw w, OI vx x, OI vy y, OI vz z)+  where+    vw  = new w+    vx  = new x+    vy  = new y+    vz  = new z+    io  = (,,,) +      <$> lazy (deref vw) +      <*> lazy (deref vx) +      <*> lazy (deref vy)+      <*> lazy (deref vz)++-- | Decomposer for 5-tuple+deTuple5 :: OI (a,b,c,d,e) -> (OI a, OI b, OI c, OI d, OI e)+deTuple5 (OI vvwxyz ~(v,w,x,y,z)) = put io vvwxyz+  `pseq` (OI vv v, OI vw w, OI vx x, OI vy y, OI vz z)+  where+    vv  = new v+    vw  = new w+    vx  = new x+    vy  = new y+    vz  = new z+    io  = (,,,,) +      <$> lazy (deref vv) +      <*> lazy (deref vw) +      <*> lazy (deref vx) +      <*> lazy (deref vy)+      <*> lazy (deref vz)++-- | Decomposer for 6-tuple+deTuple6 :: OI (a,b,c,d,e,f) -> (OI a, OI b, OI c, OI d, OI e, OI f)+deTuple6 (OI vuvwxyz ~(u,v,w,x,y,z)) = put io vuvwxyz+  `pseq` (OI vu u, OI vv v, OI vw w, OI vx x, OI vy y, OI vz z)+  where+    vu  = new u+    vv  = new v+    vw  = new w+    vx  = new x+    vy  = new y+    vz  = new z+    io  = (,,,,,) +      <$> lazy (deref vu) +      <*> lazy (deref vv) +      <*> lazy (deref vw) +      <*> lazy (deref vx) +      <*> lazy (deref vy)+      <*> lazy (deref vz)++-- | Decomposer for 7-tuple+deTuple7 :: OI (a,b,c,d,e,f,g) -> (OI a, OI b, OI c, OI d, OI e, OI f, OI g)+deTuple7 (OI vtuvwxyz ~(t,u,v,w,x,y,z)) = put io vtuvwxyz+  `pseq` (OI vt t, OI vu u, OI vv v, OI vw w, OI vx x, OI vy y, OI vz z)+  where+    vt  = new t+    vu  = new u+    vv  = new v+    vw  = new w+    vx  = new x+    vy  = new y+    vz  = new z+    io  = (,,,,,,) +      <$> lazy (deref vt) +      <*> lazy (deref vu) +      <*> lazy (deref vv) +      <*> lazy (deref vw) +      <*> lazy (deref vx) +      <*> lazy (deref vy)+      <*> lazy (deref vz)++deLeft  :: OI (Either a b) -> Either (OI a) (OI b)+deRight :: OI (Either a b) -> Either (OI a) (OI b)++deLeft (OI ve ~(Left a)) = put io ve `pseq` Left (OI vl a)+  where+    vl = new a+    io = Left <$> lazy (deref vl)++deRight (OI ve ~(Right b)) = put io ve `pseq` Right (OI vr b)+  where+    vr = new b+    io = Right <$> lazy (deref vr)++-- | Drive interaction+run :: (OI a -> b) -> IO b+run pmain = do +  { v <- newEmptyMVar+  ; x <- lazy (deref v)+  ; return $! pmain (OI v x)+  }++-- | Convert IO to interaction+iooi :: IO a -> OI a -> a+iooi io (OI var val) = put io var `pseq` val++data IOResult a = Success a | Failure String++instance Functor IOResult where+  fmap f (Success x) = Success (f x)+  fmap _ (Failure s) = Failure s++instance (Show a) => Show (IOResult a) where+  show (Success x) = show x+  show (Failure s) = "Failure: "++s++iooi' :: IO a -> OI (IOResult a) -> IOResult a+iooi' io (OI var val)+  = put ( do { r <- try io+             ; case r of { Left  e -> return $ Failure (show (e :: SomeException))+                         ; Right a -> return $ Success a }}+        ) var `par` val++-- | Forcing utilities++forces :: [()] -> ()+forces = force . dropWhile (()==)++force :: a -> ()+force x = x `pseq` ()++split :: a -> (a,())+split x = x `pseq` (x,())++-- Wrapper++type LeftValueOf  a = MVar (IO a)+type RightValueOf a = a++new :: a -> LeftValueOf a+new   = unsafeNew++deref :: MVar a -> a+deref = unsafeDeref++put   :: a -> MVar a -> a+put   = unsafePut++lazy :: IO a -> IO a+lazy = unsafeInterleaveIO++-- Unsafe primitive++unsafeNew :: a -> LeftValueOf a+unsafeNew _ = unsafePerformIO newEmptyMVar++unsafeDeref :: MVar a -> a+unsafeDeref = unsafePerformIO . readMVar++unsafePut :: a -> MVar a -> a+unsafePut x v = unsafePerformIO $ do+              { s <- tryPutMVar v x+              ; if s then return x else readMVar v+              }+
+ src/Data/OI/Combinator.hs view
@@ -0,0 +1,98 @@+-- |+-- Module      : Data.OI.Combinator+-- Copyright   : (c) Nobuo Yamashita 2011-2012+-- License     : BSD3+-- Author      : Nobuo Yamashita+-- Maintainer  : nobsun@sampou.org+-- Stability   : experimental+--+{-# LANGUAGE TypeOperators+            ,BangPatterns+  #-}+module Data.OI.Combinator+  (+   -- * Utility functions+   (|>)+  ,choice+   -- * Interaction Combinators+  ,(|:|)+  ,(|>|),(|/|)+  ,(|><|)+   -- * Iteration+  ,mapOI+  ,zipWithOI+  ,zipWithOI'+   -- * Conditional Choice+  ,ifOI+  ,choiceOI+   -- * Sequencing+  ,seqsOI+  ,seqsOI'+  ) where++import Data.OI.Base++(|>) :: (a -> b) -> (b -> c) -> (a -> c)+(|>) = flip (.)++choice :: a -> a -> Bool -> a+choice t f c = if c then t else f++-- | Connect two interactions into an interaction++infixl 3 |:|+infixl 2 |>|,|/|+infixl 1 |><|++(|:|) :: (a :-> c) -> (b :-> d) -> ((a,b) :-> (c,d))+(f |:| g) o = case dePair o of (a,b) -> (f a, g b)++(|>|) :: (a :-> (p,c)) -> (b :-> (p -> d)) -> ((a,b) :-> (c,d))+(f |>| g) o = case dePair o of (a,b) -> (c, g b p) where (p,c) = f a++(|/|) :: (a :-> c) -> (c -> (b :-> d)) -> ((a,b) :-> d)+(f |/| g) o = case dePair o of (a,b) -> g (f a) b++(|><|) :: (a :-> (p -> (q,c)))+       -> (b :-> (q -> (p,d)))+       -> ((a,b) :-> (c,d))+(f |><| g) o = case dePair o of+  (a,b) -> (c,d) where (q,c) = f a p; (p,d) = g b q++-- | Iteration++mapOI :: (a :-> b) -> ([a] :-> [b])+mapOI f os = case deList os of +  Just (x,xs) -> f x : mapOI f xs+  _           -> []++zipWithOI :: (a :-> (b -> c)) -> ([a] :-> ([b] -> [c]))+zipWithOI _ _  [] = []+zipWithOI f os (b:bs) = case deList os of+  Just (x,xs) -> f x b : zipWithOI f xs bs+  _          -> []++zipWithOI' :: (a -> (b :-> c)) -> ([a] -> ([b] :-> [c]))+zipWithOI' = flip . zipWithOI . flip++-- | Conditional branching++ifOI :: Bool -> (a :-> c) -> (b :-> c) -> (Either a b :-> c)+ifOI True  t _ o = case deLeft o of+  Left x  -> t x+  _       -> error "ifOI: Left expected but Right"+ifOI False _ e o = case deRight o of+  Right y -> e y+  _       -> error "ifOI: Right expected but Left"++choiceOI :: (a :-> c) -> (b :-> c) -> Bool -> (Either a b :-> c)+choiceOI = flip . flip ifOI++-- | Sequencing+seqsOI :: [a] :-> ([a :-> b] -> ())+seqsOI os is = case dropWhile (()==) $ map force $ zipWithOI (flip id) os is of+  [] -> ()+  _  -> error "seqsOI: Impossible!"++seqsOI' :: [a :-> b] -> ([a] :-> ())+seqsOI' = flip seqsOI
+ src/Data/OI/IO.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE TypeOperators #-}+-- |+-- Module      : Data.OI.IO+-- Copyright   : (c) Nobuo Yamashita 2011-2012+-- License     : BSD3+-- Author      : Nobuo Yamashita+-- Maintainer  : nobsun@sampou.org+-- Stability   : experimental+--+module Data.OI.IO+  (+  -- * I/O oprations+   openFile+  ,hIsClosed+  ,hIsEOF+  ,hGetLine+  ,hClose+  ,hPutStrLn+  ,isEOF+  ,getLine+  ,putStrLn+  ) where++import Data.OI.Base+import System.IO (IOMode(..),Handle)+import qualified System.IO as IO+import System.FilePath+import Prelude hiding (getLine,putStrLn)++type a :=> b = OI (IOResult a) -> IOResult b++openFile :: FilePath -> IOMode -> Handle :=> Handle+openFile = (iooi' .) . IO.openFile++hIsClosed :: IO.Handle -> Bool :=> Bool+hIsClosed = iooi' . IO.hIsClosed++hIsEOF :: IO.Handle -> Bool :=> Bool+hIsEOF = iooi' . IO.hIsEOF++hGetLine :: IO.Handle -> String :=> String+hGetLine = iooi' . IO.hGetLine++hClose :: IO.Handle -> () :=> ()+hClose = iooi' . IO.hClose++hPutStrLn :: IO.Handle -> String -> () :=> ()+hPutStrLn = (iooi' .) . IO.hPutStrLn++isEOF :: Bool :=> Bool+isEOF = iooi' IO.isEOF++getLine :: String :=> String+getLine = iooi' IO.getLine++putStrLn :: String -> () :=> ()+putStrLn = iooi' . IO.putStrLn
+ src/Data/OI/Resource.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE TypeOperators #-}+-- |+-- Module      : Data.OI.Resource+-- Copyright   : (c) Nobuo Yamashita 2011-2012+-- License     : BSD3+-- Author      : Nobuo Yamashita+-- Maintainer  : nobsun@sampou.org+-- Stability   : experimental+--+module Data.OI.Resource+  (+  -- * Resource type+   Resource(..)+  -- * File resource+  ,inFileResource+  ,outFileResource+  -- * Resource handlers+  ,mapR+  ,mapR'+  ,filterR+  ,takeR+  ,takeR'+  ,takeWhileR+  ) where++import Control.Exception+import Data.OI.Base+import System.IO (IOMode(..))+import qualified System.IO as IO+import System.IO.Unsafe+import Prelude hiding (readFile, writeFile)++data Resource a = Resource { release :: (), stream :: [IOResult a] }++instance (Show a) => Show (Resource a) where+  show r = show (stream r)++mapR :: (a -> b) -> IOResult (Resource a) -> [b]+mapR f (Success res) = mapR' f res+mapR _ _             = []++mapR' :: (a -> b) -> Resource a -> [b]+mapR' f (Resource r (Success x:xs)) = f x : mapR' f (Resource r xs)+mapR' _ (Resource r _)              = case r of () -> []++filterR :: (a -> Bool) -> IOResult (Resource a) -> [a]+filterR p (Success res) = filterR' p res+filterR _ _             = []++filterR' :: (a -> Bool) -> Resource a -> [a]+filterR' p (Resource r (Success x:xs))+ | p x       = x : filterR' p (Resource r xs)+ | otherwise = filterR' p (Resource r xs)+filterR' _ (Resource r _) = case r of () -> []++takeR :: Integral i => i -> IOResult (Resource a) -> [a]+takeR i (Success res) = takeR' i res+takeR _ _ = []++takeR' :: Integral i => i -> Resource a -> [a]+takeR' i (Resource r (Success x:xs)) | i > 0 = x : takeR' (i-1) (Resource r xs)+takeR' _ (Resource r _)                      = case r of () -> []++takeWhileR :: (a -> Bool) -> IOResult (Resource a) -> [a]+takeWhileR p (Success res) = takeWhileR' p res+takeWhileR _ _             = []++takeWhileR' :: (a -> Bool) -> Resource a -> [a]+takeWhileR' p (Resource r (Success x:xs)) | p x = x : takeWhileR' p (Resource r xs)+takeWhileR' _ _                                 = []++inFileResource :: FilePath -> IOResult (Resource String) :-> IOResult (Resource String)+inFileResource = iooi' . readFileIO++readFileIO :: FilePath -> IO (Resource String)+readFileIO fp = do+  { h <- lazy $ IO.openFile fp ReadMode+  ; r <- lazy $ IO.hClose h+  ; s <- lazy $ getlines r h+  ; return (Resource { release = r, stream = s })+  }+  where+    getlines r hdl = do +      { el <- lazy $ try $ IO.hGetLine hdl+      ; case el of+          Left  e -> case r of () -> return [Failure $ show $ (e :: SomeException)]+          Right l -> do { ls <- lazy $ getlines r hdl+                        ; return (Success l:ls)+                        }+      }++outFileResource :: FilePath -> [String] -> IOResult (Resource ()) :-> IOResult (Resource ())+outFileResource = (iooi' .) . writeFileIO++writeFileIO :: FilePath -> [String] -> IO (Resource ())+writeFileIO fp lls = do+  { h <- lazy $ IO.openFile fp WriteMode+  ; r <- lazy $ IO.hClose h+  ; s <- lazy $ putlines r h lls+  ; return (Resource { release = r, stream = s })+  }+  where+    putlines r hdl []  = IO.hFlush hdl >> case r of () -> return []+    putlines r hdl (l:ls) = do +      { eu <- lazy $ try $ IO.hPutStrLn hdl l+      ; case eu of+          Left  e -> case r of () -> return [Failure $ show $ (e :: SomeException)]+          Right u -> do { us <- lazy $ putlines r hdl ls+                        ; return (Success u:us)+                        }+      }++lazy :: IO a -> IO a+lazy = unsafeInterleaveIO
+ src/Data/OI/System.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE TypeOperators+  #-}++module Data.OI.System +  (+   args+  ,progName+  ,environment+  )+ where++import System.Environment+import Data.OI.Base++args :: [String] :-> [String]+args = iooi getArgs++progName :: String :-> String+progName = iooi getProgName++environment :: [(String, String)] :-> [(String, String)]+environment = iooi getEnvironment++