Skip to content

Commit

Permalink
Fix tests and more examples
Browse files Browse the repository at this point in the history
  • Loading branch information
tomjaguarpaw committed Feb 10, 2024
1 parent 97e0f52 commit 9771ed9
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 8 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* Benchmarks (against `effectful` particularly)

* Doctests

# Acknowledgements

* Oleg Kiselyov for his work on effects and delimited continuations
Expand Down
54 changes: 54 additions & 0 deletions bluefin-internal/src/Bluefin/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ examplePut = runEff $ runState 10 $ \st -> do
put st 30
pure ()

-- |
-- @
-- >>> runEff $ runState 10 $ \\st -> do
-- modify st (* 2)
-- ((), 20)
-- @
modify ::
(st :> effs) =>
State s st ->
Expand All @@ -242,6 +248,10 @@ modify state f = do
s <- get state
put state (f s)

modifyExample :: ((), Int)
modifyExample = runEff $ runState 10 $ \st -> do
modify st (* 2)

-- This is roughly how effectful does it
data MyException where
MyException :: e -> Data.Unique.Unique -> MyException
Expand All @@ -260,6 +270,13 @@ withScopedException_ f = do
-- unsafeCoerce is very unpleasant
if tag == fresh then Just (unsafeCoerce e) else Nothing

-- |
-- @
-- >>> runEff $ runState 10 $ \\st -> do
-- n <- get st
-- pure (2 * n)
-- (20,10)
-- @
runState ::
-- | Initial state
s ->
Expand All @@ -282,6 +299,14 @@ yieldCoroutine ::
Eff effs b
yieldCoroutine (Coroutine f) a = Eff (f a)

-- |
-- @
-- >>> runEff $ yieldToList $ \\y -> do
-- yield y 1
-- yield y 2
-- yield y 100
-- ([1,2,100], ())
-- @
yield ::
(e1 :> effs) =>
Stream a e1 ->
Expand All @@ -290,6 +315,12 @@ yield ::
Eff effs ()
yield = yieldCoroutine

yieldExample :: ([Int], ())
yieldExample = runEff $ yieldToList $ \y -> do
yield y 1
yield y 2
yield y 100

handleCoroutine ::
(a -> Eff effs b) ->
(z -> Eff effs r) ->
Expand All @@ -306,6 +337,11 @@ forEach ::
Eff effs r
forEach f h = unsafeRemoveEff (f (Coroutine (unsafeUnEff . h)))

-- |
-- @
-- >>> runEff $ yieldToList $ inFoldable [1, 2, 100]
-- ([1, 2, 100], ())
-- @
inFoldable ::
(Foldable t, e1 :> effs) =>
-- | Yield all these values from the stream
Expand All @@ -314,8 +350,16 @@ inFoldable ::
Eff effs ()
inFoldable t = for_ t . yield

inFoldableExample :: ([Int], ())
inFoldableExample = runEff $ yieldToList $ inFoldable [1, 2, 100]

-- | Pair each element in the stream with an increasing index,
-- starting from 0.
--
-- @
-- >>> runEff $ yieldToList $ enumerate (inFoldable [\"A\", \"B\", \"C\"])
-- ([(0, \"A\"), (1, \"B\"), (2, \"C\")], ())
-- @
enumerate ::
(e2 :> effs) =>
-- | ͘
Expand All @@ -327,6 +371,9 @@ enumerate ss st = evalState 0 $ \i -> forEach (insertSecond . ss) $ \s -> do
yield st (ii, s)
put i (ii + 1)

enumerateExample :: ([(Int, String)], ())
enumerateExample = runEff $ yieldToList $ enumerate (inFoldable ["A", "B", "C"])

handleException' ::
(e -> r) ->
(forall ex. Exception e ex -> Eff (ex :& effs) r) ->
Expand All @@ -353,6 +400,13 @@ earlyReturn ::
Eff effs a
earlyReturn = throw

-- |
-- @
-- >>> runEff $ evalState 10 $ \\st -> do
-- n <- get st
-- pure (2 * n)
-- 20
-- @
evalState ::
-- | Initial state
s ->
Expand Down
16 changes: 8 additions & 8 deletions bluefin-internal/test/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ main = do
assert "index 2" ([0, 1, 2, 3] !? 4 == Nothing)
assert
"Exception 1"
( runEff (handleException (eitherEff (Left True)))
( runEff (try (eitherEff (Left True)))
== (Left True :: Either Bool ())
)
assert
"Exception 2"
( runEff (handleException (eitherEff (Right True)))
( runEff (try (eitherEff (Right True)))
== (Right True :: Either () Bool)
)
assert
Expand All @@ -44,13 +44,13 @@ runTests f y = do
evalState True $ \passedAllSoFar -> do
forEach f $ \(name, passedThisOne) -> do
unless passedThisOne $
write passedAllSoFar False
put passedAllSoFar False

let mark = if passedThisOne then "" else ""

yield y (mark ++ " " ++ name)

read passedAllSoFar
get passedAllSoFar

allTrue ::
(forall e1 effs. Stream (String, Bool) e1 -> Eff (e1 :& effs) ()) ->
Expand All @@ -68,9 +68,9 @@ xs !? i = runEff $
withEarlyReturn $ \ret -> do
evalState 0 $ \s -> do
for_ xs $ \a -> do
i' <- read s
i' <- get s
when (i == i') (earlyReturn ret (Just a))
write s (i' + 1)
put s (i' + 1)
earlyReturn ret Nothing

oddsUntilFirstGreaterThan5 :: [Int]
Expand All @@ -94,9 +94,9 @@ eitherEff eith ex = case eith of

stateEff :: (e1 :> effs) => (s -> (a, s)) -> State s e1 -> Eff effs a
stateEff f st = do
s <- read st
s <- get st
let (a, s') = f s
write st s'
put st s'
pure a

listEff :: (e1 :> effs) => ([a], r) -> Stream a e1 -> Eff effs r
Expand Down

0 comments on commit 9771ed9

Please sign in to comment.