It depends on what you mean by “short-circuiting”.
- Not traversing the whole structure.
- Not running the logic you’ve passed in as a lambda over the whole structure.
(1) requires you to write your own traversal over the structure, as @cocreature says. (2), however, can be solved in several interesting, generic ways.
For example, here is a short-circuit that works to short-circuit Update
s or Script
s run through forA
or similar functions.
import DA.Foldable (forA_)
import Daml.Script
newtype ShortCircuit r e m a = ShortCircuit { runSC : r -> m (Either e a) }
deriving (Functor)
instance Action m => Applicative (ShortCircuit r e m) where
pure = ShortCircuit . const . pure . Right
ff <*> fa = do
f <- ff
f <$> fa
instance Action m => Action (ShortCircuit r e m) where
ShortCircuit fa >>= f = ShortCircuit \r ->
fa r >>= \case
Left e -> pure $ Left e
Right a -> f a `runSC` r
testSC = script do
let folded = [1, 2, 3, 4, 5] `forA_` \n -> ShortCircuit \_ -> do
debug ("Visiting " <> show n)
pure $ if n == 3 then Left n else Right ()
result <- runSC folded ()
debug $ "final result " <> show result
which has the script results
Trace:
"Visiting 1"
"Visiting 2"
"Visiting 3"
"final result Left 3"
and is guaranteed to behave exactly like this for every foldable structure.
When hand-writing a foldr
, you can take advantage of a similar phenomenon by adding another argument to the lambda you pass in:
testFR = script do
let shortAt z = foldr (\n r s ->
("visiting " <> show n) `traceRaw`
if n == z then s else r (s + n)) identity [1, 2, 3, 4, 5]
debug $ "with 3 " <> show (shortAt 3 0)
debug $ "with 42 " <> show (shortAt 42 0)
which has the result
Trace:
visiting 3
visiting 2
visiting 1
"with 3 3"
visiting 5
visiting 4
visiting 3
visiting 2
visiting 1
"with 42 15"
again, I am not stopping the fold function itself from visiting every element; however, I am stopping my own logic from being evaluated for each element, and this works for all foldable structures. Which may be sufficient, indeed even more convenient, than trying to satisfy the (1) short-circuiting definition.