content: {-# LANGUAGE AllowAmbiguousTypes #-}
  {-# LANGUAGE TemplateHaskell #-}
  
  -- SPDX-License-Identifier: MPL-2.0
  
  module Main where
  
  import Control.Monad.Hefty (
      Eff,
      Effect,
      FOEs,
      interposeBy,
      interpret,
      liftIO,
      makeEffectF,
      makeEffectH,
      runEff,
      (&),
      (:>),
      type (~>),
      type (~~>),
   )
  
  type ForkID = Int
  
  data Fork :: Effect where
      Fork :: Fork f ForkID
  makeEffectF ''Fork
  
  runForkSingle :: Eff (Fork ': es) ~> Eff es
  runForkSingle = interpret \Fork -> pure 0
  
  data ResetFork f a where
      ResetFork :: (Monoid w) => f w -> ResetFork f w
  makeEffectH ''ResetFork
  
  applyResetFork :: (Fork :> es, FOEs es) => Int -> ResetFork ~~> Eff es
  applyResetFork numberOfFork (ResetFork m) =
      m & interposeBy pure \Fork resume -> do
          r <- mapM resume [1 .. numberOfFork]
          pure $ mconcat r
  
  main :: IO ()
  main =
      runEff
          . runForkSingle
          . interpret (applyResetFork 4)
          $ do
              liftIO . putStrLn . (("[out of scope] " ++) . show) =<< fork
              s <- resetFork do
                  fid1 <- fork
                  fid2 <- fork
                  liftIO $ putStrLn $ "[delimited continuation of `fork`] Fork ID: " ++ show (fid1, fid2)
                  pure $ show (fid1, fid2)
              liftIO $ putStrLn $ "scope exited. result: " ++ s
  
  {-
  [out of scope] 0
  [delimited continuation of `fork`] Fork ID: (1,1)
  [delimited continuation of `fork`] Fork ID: (1,2)
  [delimited continuation of `fork`] Fork ID: (1,3)
  [delimited continuation of `fork`] Fork ID: (1,4)
  [delimited continuation of `fork`] Fork ID: (2,1)
  [delimited continuation of `fork`] Fork ID: (2,2)
  [delimited continuation of `fork`] Fork ID: (2,3)
  [delimited continuation of `fork`] Fork ID: (2,4)
  [delimited continuation of `fork`] Fork ID: (3,1)
  [delimited continuation of `fork`] Fork ID: (3,2)
  [delimited continuation of `fork`] Fork ID: (3,3)
  [delimited continuation of `fork`] Fork ID: (3,4)
  [delimited continuation of `fork`] Fork ID: (4,1)
  [delimited continuation of `fork`] Fork ID: (4,2)
  [delimited continuation of `fork`] Fork ID: (4,3)
  [delimited continuation of `fork`] Fork ID: (4,4)
  scope exited. result: (1,1)(1,2)(1,3)(1,4)(2,1)(2,2)(2,3)(2,4)(3,1)(3,2)(3,3)(3,4)(4,1)(4,2)(4,3)(4,4)
  -}
  