{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE TemplateHaskell #-}
module Polysemy.NonDet
(
NonDet (..)
, runNonDet
) where
import Control.Applicative
import Polysemy.Internal
import Polysemy.Internal.NonDet
import Polysemy.Internal.Union
import Polysemy.Internal.Effect
runNonDetC :: (Alternative f, Applicative m) => NonDetC m a -> m (f a)
runNonDetC (NonDetC m) = m (fmap . (<|>) . pure) (pure empty)
{-# INLINE runNonDetC #-}
newtype NonDetC m a = NonDetC
{
unNonDetC :: forall b . (a -> m b -> m b) -> m b -> m b
}
deriving (Functor)
instance Applicative (NonDetC m) where
pure a = NonDetC (\ cons -> cons a)
{-# INLINE pure #-}
NonDetC f <*> NonDetC a = NonDetC $ \ cons ->
f (\ f' -> a (cons . f'))
{-# INLINE (<*>) #-}
instance Alternative (NonDetC m) where
empty = NonDetC (\ _ nil -> nil)
{-# INLINE empty #-}
NonDetC l <|> NonDetC r = NonDetC $ \ cons -> l cons . r cons
{-# INLINE (<|>) #-}
instance Monad (NonDetC m) where
NonDetC a >>= f = NonDetC $ \ cons ->
a (\ a' -> unNonDetC (f a') cons)
{-# INLINE (>>=) #-}
runNonDet :: Alternative f => Sem (NonDet ': r) a -> Sem r (f a)
runNonDet (Sem m) = Sem $ \k -> runNonDetC $ m $ \u ->
case decomp u of
Left x -> NonDetC $ \cons nil -> do
z <- k $ weave [()] (fmap concat . traverse runNonDet) x
foldr cons nil z
Right (Yo Empty _ _ _) -> empty
Right (Yo (Choose ek) s _ y) -> do
z <- pure (ek True) <|> pure (ek False)
pure $ y $ z <$ s