packages feed

bluefin-internal 0.0.10.0 → 0.0.11.0

raw patch · 4 files changed

+148/−21 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Bluefin.Internal: makeOp :: Eff (e :& e) r -> Eff e r
+ Bluefin.Internal: subsume2 :: (e1 `In` e2) -> (e1 :& e2) `In` e2
+ Bluefin.Internal: useImplUnder :: e :> es => Eff (e1 :& e) r -> Eff (e1 :& es) r
+ Bluefin.Internal: withEffToIO_ :: e :> es => IOE e -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
+ Bluefin.Internal: withEffToIO_' :: e2 :> es => IOE e2 -> ((forall r. (forall e1. IOE e1 -> Eff (e1 :& es) r) -> IO r) -> IO a) -> Eff es a
+ Bluefin.Internal.Examples: MkCounter7 :: (forall e'. Exception () e' -> Eff (e' :& e) ()) -> State Int e -> Stream String e -> Counter7 e
+ Bluefin.Internal.Examples: [counter7State] :: Counter7 e -> State Int e
+ Bluefin.Internal.Examples: [counter7Stream] :: Counter7 e -> Stream String e
+ Bluefin.Internal.Examples: [incCounter7Impl] :: Counter7 e -> forall e'. Exception () e' -> Eff (e' :& e) ()
+ Bluefin.Internal.Examples: data Counter7 e
+ Bluefin.Internal.Examples: exampleCounter7A :: ([String], Int)
+ Bluefin.Internal.Examples: exampleCounter7B :: ([String], Int)
+ Bluefin.Internal.Examples: getCounter7 :: e :> es => Counter7 e -> String -> Eff es Int
+ Bluefin.Internal.Examples: incCounter7 :: (e :> es, e1 :> es) => Counter7 e -> Exception () e1 -> Eff es ()
+ Bluefin.Internal.Examples: instance Bluefin.Internal.Handle Bluefin.Internal.Examples.Counter5
+ Bluefin.Internal.Examples: instance Bluefin.Internal.Handle Bluefin.Internal.Examples.Counter6
+ Bluefin.Internal.Examples: instance Bluefin.Internal.Handle Bluefin.Internal.Examples.Counter7
+ Bluefin.Internal.Examples: runCounter7 :: e1 :> es => Stream String e1 -> (forall e. Counter7 e -> Eff (e :& es) r) -> Eff es Int
- Bluefin.Internal.Examples: MkApplication :: (String -> Int -> Eff e [String]) -> State (Int, Bool) e -> Stream String e -> Application e
+ Bluefin.Internal.Examples: MkApplication :: (forall e'. String -> Int -> Eff (e' :& e) [String]) -> State (Int, Bool) e -> Stream String e -> Application e
- Bluefin.Internal.Examples: MkCounter5 :: Eff e () -> (String -> Eff e Int) -> Counter5 e
+ Bluefin.Internal.Examples: MkCounter5 :: (forall e'. Eff (e' :& e) ()) -> (forall e'. String -> Eff (e' :& e) Int) -> Counter5 e
- Bluefin.Internal.Examples: MkCounter6 :: Eff e () -> State Int e -> Stream String e -> Counter6 e
+ Bluefin.Internal.Examples: MkCounter6 :: (forall e'. Eff (e' :& e) ()) -> State Int e -> Stream String e -> Counter6 e
- Bluefin.Internal.Examples: [getCounter5Impl] :: Counter5 e -> String -> Eff e Int
+ Bluefin.Internal.Examples: [getCounter5Impl] :: Counter5 e -> forall e'. String -> Eff (e' :& e) Int
- Bluefin.Internal.Examples: [incCounter5Impl] :: Counter5 e -> Eff e ()
+ Bluefin.Internal.Examples: [incCounter5Impl] :: Counter5 e -> forall e'. Eff (e' :& e) ()
- Bluefin.Internal.Examples: [incCounter6Impl] :: Counter6 e -> Eff e ()
+ Bluefin.Internal.Examples: [incCounter6Impl] :: Counter6 e -> forall e'. Eff (e' :& e) ()
- Bluefin.Internal.Examples: [queryDatabase] :: Application e -> String -> Int -> Eff e [String]
+ Bluefin.Internal.Examples: [queryDatabase] :: Application e -> forall e'. String -> Int -> Eff (e' :& e) [String]

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+## 0.0.11.0++* Add `withEffToIO_`, `useImplUnder`, `makeOp`++* Soft deprecate `withEffToIO`, `useImplWithin`+ ## 0.0.10.0  * Add `Bluefin.Internal.System.IO`
bluefin-internal.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               bluefin-internal-version:            0.0.10.0+version:            0.0.11.0 license:            MIT license-file:       LICENSE author:             Tom Ellis
src/Bluefin/Internal.hs view
@@ -58,7 +58,7 @@ runEffReader :: r -> EffReader r es a -> Eff es a runEffReader r (MkEffReader m) = m r --- This is possibly what @withRunInIO@ should morally be.+-- | Deprecated.  Use @withEffToIO_@ instead. withEffToIO ::   (e2 :> es) =>   -- | Continuation with the unlifting function in scope.@@ -75,8 +75,29 @@   Eff es a withEffToIO' io k = withEffToIO k io +withEffToIO_ ::+  (e :> es) =>+  IOE e ->+  -- | Continuation with the unlifting function in scope.+  ((forall r. Eff es r -> IO r) -> IO a) ->+  Eff es a+withEffToIO_ io k =+  withEffToIO (\effToIO -> k (\eff -> effToIO (\_ -> useImpl eff))) io++-- We can do the old API in terms of withEffToIO_+withEffToIO_' ::+  (e2 :> es) =>+  IOE e2 ->+  -- | Continuation with the unlifting function in scope.+  ((forall r. (forall e1. IOE e1 -> Eff (e1 :& es) r) -> IO r) -> IO a) ->+  Eff es a+withEffToIO_' io k =+  withEffToIO_ io (\effToIO -> k (\eff -> effToIO (weakenEff (subsume2 has) (eff io))))+ -- We don't try to do anything sophisticated here.  I haven't thought -- through all the consequences.++-- | You probably want to use 'withEffToIO_' instead. instance (e :> es) => MonadUnliftIO (EffReader (IOE e) es) where   withRunInIO ::     ((forall a. EffReader (IOE e) es a -> IO a) -> IO b) ->@@ -261,9 +282,21 @@ inContext = weakenEff (subsume1 has)  -- | Used to define dynamic effects.+makeOp :: Eff (e :& e) r -> Eff e r+makeOp = inContext++-- | Used to define dynamic effects. useImpl :: (e :> es) => Eff e r -> Eff es r useImpl = weakenEff has +-- | Like 'useImpl'+useImplUnder ::+  (e :> es) =>+  Eff (e1 :& e) r ->+  -- | ͘+  Eff (e1 :& es) r+useImplUnder = insertManySecond+ -- | Used to define handlers of compound effects. useImplIn ::   (e :> es) =>@@ -273,7 +306,7 @@   Eff es r useImplIn f h = inContext (f h) --- | Like 'useImplIn'+-- | Deprecated.  Use 'useImplUnder' instead. useImplWithin ::   (e :> es) =>   (t -> Eff (e1 :& e) r) ->@@ -309,15 +342,15 @@ -- -- @ -- data Application e = MkApplication---   { queryDatabase :: String -> Int -> Eff e [String],+--   { queryDatabase :: forall e'. String -> Int -> Eff (e' :& e) [String], --     applicationState :: State (Int, Bool) e, --     logger :: Stream String e --   } -- @ -- -- To define @mapHandle@ for @Application@ you should apply--- @mapHandle@ to all the fields that are themeselevs handles and--- apply @useImpl@ to all the fields that are dynamic effects:+-- @mapHandle@ to all the fields that are themeselves handles and+-- apply @useImplUnder@ to all the fields that are dynamic effects: -- -- @ -- instance Handle Application where@@ -328,16 +361,11 @@ --         logger = l --       } = --       MkApplication---         { queryDatabase = (fmap . fmap) useImpl q,+--         { queryDatabase = \s i -> useImplUnder (q s i), --           applicationState = mapHandle a, --           logger = mapHandle l --         } -- @------ Note that preceding @useImpl@ on the dynamic effect there is one--- fmap per @->@ that appears in type of the dynamic effect.  That is,--- @queryDatabase@ has type @String -> Int -> Eff e [String]@, which--- has two @->@, so there are two @fmap@s before @useImpl@. class Handle (h :: Effects -> Type) where   -- | Used to create compound effects, i.e. handles that contain   -- other handles.@@ -402,6 +430,9 @@ subsume1 :: (e2 `In` e1) -> (e1 :& e2) `In` e1 subsume1 i = cmp (bimap (eq (# #)) i) (merge (# #)) +subsume2 :: (e1 `In` e2) -> (e1 :& e2) `In` e2+subsume2 i = cmp (bimap i (eq (# #))) (merge (# #))+ -- | Effect subset constraint class (es1 :: Effects) :> (es2 :: Effects) @@ -520,7 +551,7 @@ -- @ -- -- @--- Caught ErrorCall:+-- Caught IOException: -- \/tmp\/doesnt-exist: openFile: does not exist (No such file or directory) -- @ rethrowIO ::
src/Bluefin/Internal/Examples.hs view
@@ -614,15 +614,22 @@ -- Counter 5  data Counter5 e = MkCounter5-  { incCounter5Impl :: Eff e (),-    getCounter5Impl :: String -> Eff e Int+  { incCounter5Impl :: forall e'. Eff (e' :& e) (),+    getCounter5Impl :: forall e'. String -> Eff (e' :& e) Int   } +instance Handle Counter5 where+  mapHandle c =+    MkCounter5+      { incCounter5Impl = useImplUnder (incCounter5Impl c),+        getCounter5Impl = \msg -> useImplUnder (getCounter5Impl c msg)+      }+ incCounter5 :: (e :> es) => Counter5 e -> Eff es ()-incCounter5 e = useImpl (incCounter5Impl e)+incCounter5 e = makeOp (incCounter5Impl (mapHandle e))  getCounter5 :: (e :> es) => Counter5 e -> String -> Eff es Int-getCounter5 e msg = useImpl (getCounter5Impl e msg)+getCounter5 e msg = makeOp (getCounter5Impl (mapHandle e) msg)  runCounter5 ::   (e1 :> es) =>@@ -667,13 +674,21 @@ -- Counter 6  data Counter6 e = MkCounter6-  { incCounter6Impl :: Eff e (),+  { incCounter6Impl :: forall e'. Eff (e' :& e) (),     counter6State :: State Int e,     counter6Stream :: Stream String e   } +instance Handle Counter6 where+  mapHandle c =+    MkCounter6+      { incCounter6Impl = useImplUnder (incCounter6Impl c),+        counter6State = mapHandle (counter6State c),+        counter6Stream = mapHandle (counter6Stream c)+      }+ incCounter6 :: (e :> es) => Counter6 e -> Eff es ()-incCounter6 e = useImpl (incCounter6Impl e)+incCounter6 e = makeOp (incCounter6Impl (mapHandle e))  getCounter6 :: (e :> es) => Counter6 e -> String -> Eff es Int getCounter6 (MkCounter6 _ st y) msg = do@@ -719,6 +734,81 @@ -- > exampleCounter6 -- (["Count was even","I'm getting the counter","n was 2, as expected"],2) +-- Counter 7++data Counter7 e = MkCounter7+  { incCounter7Impl :: forall e'. Exception () e' -> Eff (e' :& e) (),+    counter7State :: State Int e,+    counter7Stream :: Stream String e+  }++instance Handle Counter7 where+  mapHandle c =+    MkCounter7+      { incCounter7Impl = \ex -> useImplUnder (incCounter7Impl c ex),+        counter7State = mapHandle (counter7State c),+        counter7Stream = mapHandle (counter7Stream c)+      }++incCounter7 ::+  (e :> es, e1 :> es) => Counter7 e -> Exception () e1 -> Eff es ()+incCounter7 e ex = makeOp (incCounter7Impl (mapHandle e) (mapHandle ex))++getCounter7 :: (e :> es) => Counter7 e -> String -> Eff es Int+getCounter7 (MkCounter7 _ st y) msg = do+  yield y msg+  get st++runCounter7 ::+  (e1 :> es) =>+  Stream String e1 ->+  (forall e. Counter7 e -> Eff (e :& es) r) ->+  Eff es Int+runCounter7 y k =+  evalState 0 $ \st -> do+    _ <-+      useImplIn+        k+        ( MkCounter7+            { incCounter7Impl = \ex -> do+                count <- get st++                when (even count) $+                  yield y "Count was even"++                when (count >= 10) $+                  throw ex ()++                put st (count + 1),+              counter7State = mapHandle st,+              counter7Stream = mapHandle y+            }+        )+    get st++exampleCounter7A :: ([String], Int)+exampleCounter7A = runPureEff $ yieldToList $ \y -> do+  handle (\() -> pure (-42)) $ \ex ->+    runCounter7 y $ \c -> do+      incCounter7 c ex+      incCounter7 c ex+      n <- getCounter7 c "I'm getting the counter"+      when (n == 2) $+        yield y "n was 2, as expected"++-- > exampleCounter7A+-- (["Count was even","I'm getting the counter","n was 2, as expected"],2)++exampleCounter7B :: ([String], Int)+exampleCounter7B = runPureEff $ yieldToList $ \y -> do+  handle (\() -> pure (-42)) $ \ex ->+    runCounter7 y $ \c -> do+      forever (incCounter7 c ex)++-- > exampleCounter7B+-- (["Count was even","Count was even","Count was even","Count was even","Count was even","Count was even"],-42)++ -- FileSystem  data FileSystem es = MkFileSystem@@ -802,7 +892,7 @@ -- instance Handle example  data Application e = MkApplication-  { queryDatabase :: String -> Int -> Eff e [String],+  { queryDatabase :: forall e'. String -> Int -> Eff (e' :& e) [String],     applicationState :: State (Int, Bool) e,     logger :: Stream String e   }@@ -815,7 +905,7 @@         logger = l       } =       MkApplication-        { queryDatabase = (fmap . fmap) useImpl q,+        { queryDatabase = \s i -> useImplUnder (q s i),           applicationState = mapHandle a,           logger = mapHandle l         }