transformers-eff-0.1.0.0: Control/Effect/Nondeterminism.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
module Control.Effect.Nondeterminism where
import Control.Monad (join)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Cont (shiftT)
import Control.Effect
import qualified Pipes as P
import qualified Pipes.Prelude as P
-- TODO Can probably generalize over any foldable.
class Monad m => Nondeterministic m where
liftNondeterminism :: [a] -> m a
instance Monad m => Nondeterministic (Eff [] m) where
liftNondeterminism = interpret
{-# INLINE liftNondeterminism #-}
instance {-# OVERLAPPABLE #-} (Nondeterministic m) => Nondeterministic (Eff f m) where
liftNondeterminism = lift . liftNondeterminism
{-# INLINE liftNondeterminism #-}
choose :: Nondeterministic m => [a] -> m a
choose = liftNondeterminism
{-# INLINE choose #-}
runNondeterminism :: Monad m => Eff [] m a -> m [a]
runNondeterminism eff = P.toListM (P.enumerate (translate makeChoice eff))
where makeChoice choices =
shiftT (\k ->
lift (P.Select (P.for (P.each choices)
(P.enumerate . k))))
{-# INLINE runNondeterminism #-}
-- TODO Non-conflicting names?
mzero :: Nondeterministic m => m a
mzero = choose mempty
mplus :: Nondeterministic m => m a -> m a -> m a
mplus l r = join (choose [l,r])