packages feed

polysemy-resume-0.6.0.0: test/Polysemy/Resume/Test/InterceptTest.hs

{-# options_ghc -fplugin=Polysemy.Plugin #-}

module Polysemy.Resume.Test.InterceptTest where

import Control.Concurrent.STM (newTVarIO)
import Polysemy.Test (UnitTest, runTestAuto, (===))

import Polysemy.Resume.Effect.Resumable (type (!!))
import Polysemy.Resume.Effect.Stop (stop)
import Polysemy.Resume.Interpreter.Resumable (interceptResumable, interpretResumable)
import Polysemy.Resume.Resume (restop, (!!), (<!))

data A :: Effect where
  A1 :: A m Int
  A2 :: A m Int
  A3 :: A m Int

makeSem ''A

interpretA ::
  Member (AtomicState Int) r =>
  InterpreterFor (A !! Int) r
interpretA =
  interpretResumable \case
    A1 ->
      atomicGet >>= \case
        5 -> stop 13
        n -> pure (n - 1000)
    A2 ->
      pure (-1)
    A3 ->
      pure (-1)

interceptA1 ::
  Members [A !! Int, AtomicState Int] r =>
  Sem r a ->
  Sem r a
interceptA1 =
  interceptResumable \case
    A1 ->
      atomicModify' (8 *) *> restop a1
    A2 -> do
      atomicPut 5
      restop a1
    A3 ->
      stop (23)

interceptA2 ::
  Members [A !! Int, AtomicState Int] r =>
  Sem r a ->
  Sem r a
interceptA2 =
  interceptResumable \case
    A1 ->
      atomicModify' (500 +) *> restop a1
    A2 ->
      restop a2
    A3 ->
      99 <! a3

test_intercept :: UnitTest
test_intercept =
  runTestAuto do
    tv <- embed (newTVarIO 0)
    i <- runAtomicStateTVar tv $ interpretA $ interceptA1 $ interceptA2 do
      i1 <- a1 !! \ i -> fail ("first failed with: " <> show i)
      i2 <- a2 !! pure
      i3 <- a3 !! pure
      pure (i1, i2, i3)
    (3000, 13, 99) === i