Open treeowl opened 1 year ago
I think the previous attempt to make it lazier should be backed out, in favor of a change to the underlying queue. I realized a couple things that may be helpful for keeping things theoretically clean, while also making them lazy enough:
empty
as an empty queue, but it can alternatively be represented as a singleton queue containing pure Nothing
. That means we can actually use nonempty catenable queues instead of normal ones.Question: does this sort of thing help with any other monads?
A minimal fix to the catenable queue implementation:
C0 >< ys = ys
-- Remove this line: xs >< C0 = xs
(CN x q) >< ys = CN x (q |> ys)
tviewl C0 = TEmptyL
tviewl (CN h t) = h :| linkAll t
where
linkAll :: TSequence q => q (CTQueue q c) a b -> CTQueue q c a b
linkAll v = case tviewl v of
TEmptyL -> C0
C0 :| t -> linkAll t
CN x q :| t
| TEmptyL <- tviewl t -> CN x q
| otherwise -> CN x (q |> linkAll t)
The definition of mplus
can be simplified back to
ML xs `mplus` ML ys = ML (xs >< ys)
One caveat: that queue is used for several other monads. I have no idea whether the change makes sense for them.
Hi! Sorry for the belated response. I would also expect this lazy behavior. Your minimal fix makes sense. I think this just improves the strictness properties so I do not think it can have any adverse effects (?)
If you're looking to implement a principled data structure with the right persistently amortized bounds and then build the r-w-r stuff on top, then you need to replace the catenable list with a lazy catenable nonempty list. If you don't care about principled separation, you can make a lazy catenable list that doesn't drop empties, as I've shown, but that underlying structure doesn't have proper persistently amortized bounds—the same empties may need to be dropped multiple times.
Like I said, for LogicT
I don't think there can be bad effects, but I haven't gone through and looked at the rest.
I would expect that
would be able to produce 1 and 2 before failing, but in fact it can only produce 1. The problem is the rather aggressive
Empty
matching in the definition of><
for bootstrapped queues. The fix is to remove that. The price of the fix is that if a bunch ofempty
s in a row get<|>
ed onto the logic computation then views in multiple futures may each have to drop them. This is very similar, I think, to the cost of>=>
ing a bunch ofpure
s onto a free Kleisli category. Unfortunate, but unavoidable.