bluefin-internal 0.0.11.0 → 0.0.12.0
raw patch · 5 files changed
+104/−24 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Bluefin.Internal: asks :: e :> es => Reader r e -> (r -> a) -> Eff es a
+ Bluefin.Internal: local :: e1 :> es => Reader r e1 -> (r -> r) -> Eff es a -> Eff es a
+ Bluefin.Internal.Examples: MkCounter3B :: IOE e -> Counter3B e
+ Bluefin.Internal.Examples: exampleCounter3B :: IO ()
+ Bluefin.Internal.Examples: incCounter3B :: e :> es => Counter3B e -> Eff es ()
+ Bluefin.Internal.Examples: instance Bluefin.Internal.Handle Bluefin.Internal.Examples.FileSystem
+ Bluefin.Internal.Examples: newtype Counter3B e
+ Bluefin.Internal.Examples: runCounter3B :: e1 :> es => IOE e1 -> (forall e. Counter3B e -> Eff (e :& es) r) -> Eff es r
- Bluefin.Internal: MkReader :: r -> Reader r (e :: Effects)
+ Bluefin.Internal: MkReader :: State r e -> Reader r e
- Bluefin.Internal: newtype Reader r (e :: Effects)
+ Bluefin.Internal: newtype Reader r e
- Bluefin.Internal.Examples: MkFileSystem :: (FilePath -> Eff es String) -> (FilePath -> String -> Eff es ()) -> FileSystem es
+ Bluefin.Internal.Examples: MkFileSystem :: (forall e. FilePath -> Eff (e :& es) String) -> (forall e. FilePath -> String -> Eff (e :& es) ()) -> FileSystem es
- Bluefin.Internal.Examples: [readFileImpl] :: FileSystem es -> FilePath -> Eff es String
+ Bluefin.Internal.Examples: [readFileImpl] :: FileSystem es -> forall e. FilePath -> Eff (e :& es) String
- Bluefin.Internal.Examples: [writeFileImpl] :: FileSystem es -> FilePath -> String -> Eff es ()
+ Bluefin.Internal.Examples: [writeFileImpl] :: FileSystem es -> forall e. FilePath -> String -> Eff (e :& es) ()
Files
- CHANGELOG.md +4/−0
- bluefin-internal.cabal +1/−1
- src/Bluefin/Internal.hs +56/−13
- src/Bluefin/Internal/Examples.hs +41/−8
- test/Main.hs +2/−2
CHANGELOG.md view
@@ -1,3 +1,7 @@+## 0.0.12.0++* Add `asks` and `local`+ ## 0.0.11.0 * Add `withEffToIO_`, `useImplUnder`, `makeOp`
bluefin-internal.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: bluefin-internal-version: 0.0.11.0+version: 0.0.12.0 license: MIT license-file: LICENSE author: Tom Ellis
src/Bluefin/Internal.hs view
@@ -75,6 +75,8 @@ Eff es a withEffToIO' io k = withEffToIO k io +-- | This is equivalent to the 'withRunInIO' method of+-- 'MonadUnliftIO', but written in Bluefin-style. withEffToIO_ :: (e :> es) => IOE e ->@@ -146,18 +148,18 @@ bv <- effIO io newEmptyMVar let t1 :: forall e. IOE e -> Eff (e :& es) r- t1 io' = forEach (useImplWithin m1) $ \a -> effIO io' $ do+ t1 io' = forEach (useImplUnder . m1) $ \a -> effIO io' $ do putMVar av a takeMVar bv let t2 :: forall e. IOE e -> Eff (e :& es) r t2 io' = do ainit <- effIO io' (takeMVar av)- forEach (useImplWithin (m2 ainit)) $ \b_ -> effIO io' $ do+ forEach (useImplUnder . m2 ainit) $ \b_ -> effIO io' $ do putMVar bv b_ takeMVar av - race (useImplWithin t1) (useImplWithin t2) io+ race (useImplUnder . t1) (useImplUnder . t2) io -- | Old name for 'consumeStream'. @receiveStream@ will be deprecated -- in a future version.@@ -184,7 +186,7 @@ Eff es r zipCoroutines c m1 m2 = do connectCoroutines m1 $ \a1 c1 -> do- connectCoroutines (useImplWithin m2) $ \a2 c2 -> do+ connectCoroutines (useImplUnder . m2) $ \a2 c2 -> do evalState (a1, a2) $ \ass -> do forever $ do as <- get ass@@ -250,6 +252,10 @@ Eff es r withMonadFail f m = unEffReader m f +-- | This function is really very unsafe and for internal use only.+-- Unlike the similarly-named @unsafeEff_@ function from @effectful@,+-- which is provided for use in user code, this function must never be+-- used in user code. unsafeRemoveEff :: Eff (e :& es) a -> Eff es a unsafeRemoveEff = UnsafeMkEff . unsafeUnEff @@ -690,7 +696,7 @@ (forall e. StateSource e -> Eff (e :& es) a) -> -- | ͘ Eff es a-withStateSource f = unsafeRemoveEff (f StateSource)+withStateSource f = useImplIn f StateSource -- | -- @@@ -1155,7 +1161,7 @@ (forall e. IOE e -> Eff (e :& es) a) -> -- | ͘ Eff es a-unsafeProvideIO eff = unsafeRemoveEff (eff MkIOE)+unsafeProvideIO eff = useImplIn eff MkIOE connect :: (forall e1. Coroutine a b e1 -> Eff (e1 :& es) r1) ->@@ -1241,21 +1247,58 @@ Eff es () tell (Writer y) = yield y -newtype Reader r (e :: Effects) = MkReader r--instance Handle (Reader r) where- mapHandle (MkReader r) = MkReader r+newtype Reader r e = MkReader (State r e)+ deriving newtype (Handle) runReader ::- -- | ͘+ -- | Initial value for @Reader@. r -> (forall e. Reader r e -> Eff (e :& es) a) -> Eff es a-runReader r f = unsafeRemoveEff (f (MkReader r))+runReader r f = evalState r (f . MkReader) +-- | Read the value. Note that @ask@ has the property that these two+-- operations are always equivalent:+--+-- @+-- do+-- r1 <- ask re+-- r2 <- ask re+-- pure (r1, r2)+-- @+--+-- @+-- do+-- r <- ask re+-- pure (r, r)+-- @ ask :: (e :> es) => -- | ͘ Reader r e -> Eff es r-ask (MkReader r) = pure r+ask (MkReader st) = get st++-- | Read the value modified by a function+asks ::+ (e :> es) =>+ Reader r e ->+ -- | Read the value modified by this function+ (r -> a) ->+ Eff es a+asks (MkReader st) f = fmap f (get st)++local ::+ (e1 :> es) =>+ Reader r e1 ->+ -- | In the body, the reader value is modified by this function.+ (r -> r) ->+ -- | Body+ Eff es a ->+ Eff es a+local (MkReader st) f k = do+ orig <- get st+ bracket+ (put st (f orig))+ (\() -> put st orig)+ (\() -> k)
src/Bluefin/Internal/Examples.hs view
@@ -192,7 +192,7 @@ (pure ()) (\() -> effIO io (putStrLn "Released")) $ \() -> do- consumeEach (useImplWithin k) $ do+ consumeEach (useImplUnder . k) $ do (x, xs) <- get s >>= \case [] -> jumpTo done@@ -207,7 +207,7 @@ Consume a e3 -> Eff es () takeRec n k rec =- withJump $ \done -> evalState n $ \s -> consumeEach (useImplWithin k) $ do+ withJump $ \done -> evalState n $ \s -> consumeEach (useImplUnder . k) $ do s' <- get s if s' <= 0 then jumpTo done@@ -244,7 +244,7 @@ mapRec (subtract 1) $ takeRec 3 $ traverseRec (effIO io . print) $- useImplWithin x+ useImplUnder . x awaitExample :: IO () awaitExample = runEff $ \io -> do@@ -507,7 +507,7 @@ incCounter1 c incCounter1 c --- > exampeleCounter1+-- > exampleCounter1 -- 3 -- Counter 2@@ -566,6 +566,32 @@ -- > exampleCounter3 -- 10 +-- Counter 3B++newtype Counter3B e = MkCounter3B (IOE e)++incCounter3B :: (e :> es) => Counter3B e -> Eff es ()+incCounter3B (MkCounter3B io) =+ effIO io (putStrLn "You tried to increment the counter")++runCounter3B ::+ (e1 :> es) =>+ IOE e1 ->+ (forall e. Counter3B e -> Eff (e :& es) r) ->+ Eff es r+runCounter3B io k = useImplIn k (MkCounter3B (mapHandle io))++exampleCounter3B :: IO ()+exampleCounter3B = runEff $ \io -> runCounter3B io $ \c -> do+ incCounter3B c+ incCounter3B c+ incCounter3B c++-- ghci> exampleCounter3B+-- You tried to increment the counter+-- You tried to increment the counter+-- You tried to increment the counter+ -- Counter 4 data Counter4 e@@ -812,15 +838,22 @@ -- FileSystem data FileSystem es = MkFileSystem- { readFileImpl :: FilePath -> Eff es String,- writeFileImpl :: FilePath -> String -> Eff es ()+ { readFileImpl :: forall e. FilePath -> Eff (e :& es) String,+ writeFileImpl :: forall e. FilePath -> String -> Eff (e :& es) () } +instance Handle FileSystem where+ mapHandle fs = MkFileSystem {+ readFileImpl = \fp -> useImplUnder (readFileImpl fs fp),+ writeFileImpl = \fp s -> useImplUnder (writeFileImpl fs fp s)+ }+ readFile :: (e :> es) => FileSystem e -> FilePath -> Eff es String-readFile fs filepath = useImpl (readFileImpl fs filepath)+readFile fs filepath = makeOp (readFileImpl (mapHandle fs) filepath) writeFile :: (e :> es) => FileSystem e -> FilePath -> String -> Eff es ()-writeFile fs filepath contents = useImpl (writeFileImpl fs filepath contents)+writeFile fs filepath contents =+ makeOp (writeFileImpl (mapHandle fs) filepath contents) runFileSystemPure :: (e1 :> es) =>
test/Main.hs view
@@ -77,7 +77,7 @@ Eff es Bool runTests f y = do ((), All passedAll) <- runWriter $ \passedAllSoFar -> do- forEach (useImplWithin f) $ \(name, mFailure) -> do+ forEach (useImplUnder . f) $ \(name, mFailure) -> do let passed = case mFailure of Just _ -> False Nothing -> True@@ -104,7 +104,7 @@ (forall e1. SpecH e1 -> Eff (e1 :& es) ()) -> Eff es () runSpecH ioe f = do- passed <- forEach (runTests (useImplWithin f)) $ \text ->+ passed <- forEach (runTests (useImplUnder . f)) $ \text -> effIO ioe (putStrLn text) effIO ioe $ case passed of