-- Lifts a list into Amb.
amb :: [a] -> Amb a
If we assume Amb is just List, then: amb = id
If we write the example in the original article in desugared style, we get: amb [1, 2, 3] >>= \x ->
amb [4, 5, 6] >>= \y ->
if x * y /= 8 then amb [] else pure () >>
pure (x, y)
(we are forced to use an awkward condition with `pure ()` on the else branch when calling `amb` because Haskell requires us to return values on all branches. We can rewrite it equivalently in terms of `when` to hide that detail: amb [1, 2, 3] >>= \x ->
amb [4, 5, 6] >>= \y ->
when (x * y /= 8) (amb []) >>
pure (x, y)
It now looks more similar to the original example.) do x <- [1, 2, 3]
y <- [4, 5, 6]
if x * y == 8 then pure (x, y)
else []
which can be equivalently reworded as the list comprehension: [(x, y) | x <- [1, 2, 3], y <- [4, 5, 6], x * y == 8]
i.e., the underlying structure of amb without side-effects can also be understood as just a search of the input space for values that fulfill some criteria, rather than as backtracking via continuations.
Gender roles aren't so cut and dry any more. Given that, maybe outcomes should be considered independent of gender?