oi 0.0.2 → 0.0.3
raw patch · 2 files changed
+46/−10 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- oi.cabal +1/−1
- src/Data/OI.hs +45/−9
oi.cabal view
@@ -1,5 +1,5 @@ Name: oi-Version: 0.0.2+Version: 0.0.3 Category: Data Synopsis: Purely Functional Lazy Interaction with the outer world Description: This package implements a data structure and operations on it
src/Data/OI.hs view
@@ -5,20 +5,45 @@ ,BangPatterns #-} {-# OPTIONS_GHC -fno-cse #-}+-- |+-- Module : Data.OI+-- Copyright : (c) Nobuo Yamashita 2011+-- 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 ,deList++ -- * Interaction combinators ,(<|) ,mapOI ,mapOI'@@ -34,16 +59,20 @@ 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 } @@ -82,8 +111,7 @@ firstA :: (a :-> b) -> (a,c) :-> (b,c) firstA f ac = case deTuple ac of (x,z) -> (f x, (z?)) ----+-- | Embed interactions into tuple deTuple :: (a,b) :-> (OI a,OI b) deTuple (OI vxy ~(x,y)) = assign io vxy `pseq` (OI vx x, OI vy y) where@@ -91,6 +119,7 @@ vy = new () io = (,) <$> unsafeInterleaveIO (dereference vx) <*> unsafeInterleaveIO (dereference vy) +-- | Embed interactions into list deList :: [a] :-> Maybe (OI a, OI [a]) deList (OI vxxs xxs) = assign io vxxs@@ -105,72 +134,79 @@ -- infixr 1 <| +-- | Connect two interactions into an interaction (<|) :: (b -> c :-> d) -> (a :-> b) -> (a,c) :-> d (f <| g) ac = case deTuple ac of (a,c) -> f (g a) c +-- | 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 ----+-- | 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 <- unsafeInterleaveIO newEmptyMVar ; x <- unsafeInterleaveIO (dereference vx) ; return $! pmain (OI vx x) } ---+-- type LeftValueOf = MVar -{-# INLINE new #-}+{-# NOINLINE new #-} new :: () -> LeftValueOf a new _ = unsafePerformIO $ newEmptyMVar -{-# INLINE reference #-}+{-# NOINLINE reference #-} reference :: a -> LeftValueOf a reference = unsafePerformIO . newMVar -{-# INLINE dereference #-}+{-# NOINLINE dereference #-} dereference :: LeftValueOf a -> a dereference = unsafePerformIO . readMVar -{-# INLINE assign #-}+{-# NOINLINE assign #-} assign :: a -> LeftValueOf a -> a assign !x v = unsafePerformIO $ do { s <- tryPutMVar v x