From a81c611139a4bc09ff8f34534551efa712b28e15 Mon Sep 17 00:00:00 2001 From: Yamada Ryo Date: Sun, 27 Oct 2024 16:27:40 +0900 Subject: [PATCH] [add] `runNonDetIO`. --- .../src/Control/Monad/Hefty/NonDet.hs | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/heftia-effects/src/Control/Monad/Hefty/NonDet.hs b/heftia-effects/src/Control/Monad/Hefty/NonDet.hs index 9a5b4a0..95fb146 100644 --- a/heftia-effects/src/Control/Monad/Hefty/NonDet.hs +++ b/heftia-effects/src/Control/Monad/Hefty/NonDet.hs @@ -1,4 +1,6 @@ {-# LANGUAGE CPP #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} -- This Source Code Form is subject to the terms of the Mozilla Public -- License, v. 2.0. If a copy of the MPL was not distributed with this @@ -25,15 +27,20 @@ import Control.Arrow ((>>>)) import Control.Monad.Hefty ( Eff, bundleN, + interpret, interpretBy, interpretH, nil, (!+), + (&), + type (<<|), type (<|), type (~>), ) import Data.Bool (bool) import Data.Effect.NonDet +import Data.Effect.Unlift (UnliftIO) +import UnliftIO (Exception, SomeException, throwIO, try) -- | 'NonDet' effects handler for alternative answer type. runNonDet @@ -88,7 +95,7 @@ runChooseMonoid f = liftA2 (<>) (k False) (k True) -- | 'Empty' effect handler. -runEmpty :: forall a r. Eff '[] (Empty ': r) a -> Eff '[] r (Maybe a) +runEmpty :: forall a ef. Eff '[] (Empty ': ef) a -> Eff '[] ef (Maybe a) runEmpty = interpretBy (pure . Just) @@ -117,3 +124,21 @@ branch a b = do {-# INLINE branch #-} infixl 3 `branch` + +runNonDetIO + :: (UnliftIO <<| eh, IO <| ef) + => Eff (ChooseH ': eh) (Empty ': ef) a + -> Eff eh ef (Either SomeException a) +runNonDetIO m = try do + m + & interpretH + ( \(ChooseH a b) -> + try a >>= \case + Right x -> pure x + Left (_ :: SomeException) -> b + ) + & interpret (\Empty -> throwIO EmptyException) + +data EmptyException = EmptyException + deriving stock (Show) + deriving anyclass (Exception)