A software engineer website

Polysemy: NonDet

Gautier DI FOLCO February 19, 2023 [Haskell] #haskell #polysemy #design #effects systems

As seen in a previous log, some effects allow type classes to be supported.

To enable Applicative, there is the NonDet effect, which works with Error a:

failing :: Members '[Error Integer, Embed IO] r => Sem r Integer
failing = do
  embed $ putStrLn "failing"
  throw @Integer 1

working0 :: Members '[Error Integer, Embed IO] r => Sem r Integer
working0 = do
  embed $ putStrLn "working0"
  return 42

working1 :: Members '[Error Integer, Embed IO] r => Sem r Integer
working1 = do
  embed $ putStrLn "working1"
  return 42

actFailingFirst :: Members '[Error Integer, NonDet, Embed IO] r => Sem r Integer
actFailingFirst = failing <|> working0 <|> working1

Some interpreters are provided:

Let's make some tests:

putStrLn "# FailingFirst"
putStrLn "nonDetToError"
runM (runError @Integer $ nonDetToError @Integer 2 actFailingFirst) >>= print
putStrLn "## runNonDet"
runM (runError @Integer $ runNonDet @Maybe actFailingFirst) >>= print
putStrLn "## runNonDetMaybe"
runM (runError @Integer $ runNonDetMaybe actFailingFirst) >>= print
putStrLn "# WorkingFirst"
putStrLn "nonDetToError"
runM (runError @Integer $ nonDetToError @Integer 2 actWorkingFirst) >>= print
putStrLn "## runNonDet"
runM (runError @Integer $ runNonDet @Maybe actWorkingFirst) >>= print
putStrLn "## runNonDetMaybe"
runM (runError @Integer $ runNonDetMaybe actWorkingFirst) >>= print

Giving:

# FailingFirst
nonDetToError
failing
working0
Right 42
## runNonDet
failing
Left 1
## runNonDetMaybe
failing
Left 1
# WorkingFirst
nonDetToError
working0
Right 42
## runNonDet
working0
failing
Left 1
## runNonDetMaybe
working0
Right (Just 42)

Let's try to summarize:

With failing as first element of <|>:

EagerResult
nonDetToErrorxRight 42
runNonDetLeft 1
runNonDetMaybeLeft 1

With working as first element of <|>:

EagerResult
nonDetToErrorRight 42
runNonDetxLeft 1
runNonDetMaybeRight (Just 42)

See the full the code here.