-
Notifications
You must be signed in to change notification settings - Fork 0
/
NonDet.hs
54 lines (43 loc) · 1.05 KB
/
NonDet.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{-|
The `Alternative` effect.
I can't do the "return any alternative holding the result" as "polysemy" does,
because I only have `Core.plug` and it is not allowed to change the effect result.
-}
module Effect.NonDet
( -- * Interface
NonDet
-- * Implementation
, asAlternative
-- * Re-exporting core
, module Core
)
where
import Control.Applicative
import Core
import Effect.Final
import Effect.Lift
-- | The messages.
--
-- Use `empty`/`<|>`.
--
data NonDet m a where
Loose :: NonDet m a
Choose :: m a -> m a -> NonDet m a
instance Effect NonDet where
weave f Loose = Loose
weave f (Choose a b) = Choose (f a) (f b)
instance Members '[NonDet] fs => Alternative (Eff fs) where
empty = send Loose
a <|> b = send (Choose a b)
-- | Delegate to the final monad.
asAlternative
:: forall m fs
. (Members [Final m, Lift m] fs, Alternative m)
=> Eff (NonDet : fs)
~> Eff fs
asAlternative = plug \case
Loose -> lift @m $ empty
Choose a b -> do
na <- final @m a
nb <- final @m b
lift @m $ na <|> nb