@@ -359,19 +359,30 @@ withStrategyIO :: Strategy a -> a -> IO a
359
359
withStrategyIO = flip usingIO
360
360
361
361
-- | Compose two strategies sequentially.
362
- -- This is the analogue to function composition on strategies.
363
362
--
364
- -- For any strategies @strat1@, @strat2@, and @strat3@,
363
+ -- > strat2 `dot` strat1 == strat2 . withStrategy strat1
364
+ --
365
+ -- 'dot' is associative:
365
366
--
366
367
-- > (strat1 `dot` strat2) `dot` strat3 == strat1 `dot` (strat2 `dot` strat3)
367
- -- > strat1 `dot` strat1 = strat1
368
- -- > strat1 `dot` r0 == strat1
369
368
--
370
- -- > strat2 `dot` strat1 == strat2 . withStrategy strat1
369
+ -- 'r0' and 'rseq' are one-sided identities of 'dot':
370
+ --
371
+ -- > strat `dot` r0 == strat
372
+ -- > strat `dot` rseq == strat
371
373
--
374
+ -- Furthermore, since strategies should only force and spark computations
375
+ -- (that is, they don't actually change any values),
376
+ --
377
+ -- > strat `dot` strat == strat
378
+ --
379
+ -- Perhaps unexpectedly, @r0 `dot` strat == r0@.
380
+ -- 'Control.Monad.<=<' has a more intuitive behaviour (@r0 <=< strat == strat@).
372
381
dot :: Strategy a -> Strategy a -> Strategy a
373
382
strat2 `dot` strat1 = strat2 . runEval . strat1
374
383
384
+ -- Note [dot proofs]
385
+ -- ~~~~~~~~~~~~~~~~~
375
386
-- Proof of strat2 `dot` strat1 == strat2 . withStrategy strat1
376
387
--
377
388
-- strat2 . withStrategy strat1
@@ -380,17 +391,14 @@ strat2 `dot` strat1 = strat2 . runEval . strat1
380
391
-- == \x -> strat2 (runEval (strat1 x))
381
392
-- == \x -> (strat2 . runEval . strat1) x
382
393
-- == strat2 `dot` strat1
383
-
384
- -- One might be tempted to think that 'dot' is equivalent to '(<=<)',
385
- -- the right-to-left Kleisli composition in the Eval monad, because
386
- -- '(<=<)' can take the type @Strategy a -> Strategy a -> Strategy a@
387
- -- and intuitively does what 'dot' does: First apply the strategy to the
388
- -- right then the one to the left. However, there is a subtle difference
389
- -- in strictness, witnessed by the following example:
390
394
--
391
- -- > (r0 `dot` rseq) undefined == Done undefined
392
- -- > (r0 <=< rseq) undefined == undefined
395
+ -- Proof of associativity
393
396
--
397
+ -- (strat1 `dot` strat2) `dot` strat3
398
+ -- == (strat1 . runEval . strat2) . runEval . strat3
399
+ -- == strat1 . runEval . strat2 . runEval . strat3
400
+ -- == strat1 . runEval . (strat2 . runEval . strat3)
401
+ -- == strat1 `dot` (strat2 `dot` strat3)
394
402
395
403
-- | Inject a sequential strategy (i.e., coerce a sequential strategy
396
404
-- to a general strategy).
0 commit comments