Dispose with side effects
The module Data.Unrestricted.Linear provides tools for manipulating linear values non-linearly. One of them is given by the type class Consumable whose single class method consume :: a %1 -> () allows us to consume or drop a linear value of type a, by returning an unit type ().
However, sometimes consuming a linear value might cause an effect, for example deallocating a memory cell. I think it would be nice to capture situations like this in the module Data.Unrestricted.Linear by defining a type class Disposable
class Disposable a where
dispose :: a %1 -> IO ()
which would generalise Consumable
instance Consumable a => Disposable a where
dispose x = return (consume x)
Of course, something similar could be done for Dupable and Moveable.
Why not be more general?
class Monad m => Disposable m a where
dispose :: a %1 -> m ()
I'm always in favour of general solutions, so agree! 😃
I'd agree to a PR adding this.
There are discussion about disposable objects somewhere in the streaming sublibrary, in particular. So it's something that we've been thinking of around here as well.
Which order should the class parameters go in? I can't decide which partial application seems more likely.
I'm pretty sure that we want Disposable m a
Think of the original proposal that was (up to a renaming) DisposableIO a. Now it would be Disposable IO a. At the very least, it means that Disposable m a is strictly more useful than DisposableIO a, if we take the other argument order, there are at least cases where DisposableIO would be better.
But anyway, beyond what I can articulate, I'm quite sure it's the right call.
This would come in pretty useful for my reference counting library too (it's still a work in progress, I'll publish it in due time).
And Disposable is for consuming values in some monad m; however, It'd also be good to have some class Shareable, similar to Dupable but causing effects (though I'm not sure I can come up with instances for things other than the reference counted values)
class Monad m => Shareable m a where
share :: a -o m (a,a)
@alt-romes PR still welcome :slightly_smiling_face: .
I'm happy to do a PR, but I've not settled on the design.
Is Disposable the name we want? (I'll leave out Shareable for now, I've added it to my library and don't see how that name fits outside of that library)
I don't particularly like it, but did we consider something like ConsumableM and DupableM?
Ah, and I don't think we need to require the Monad constraint on Disposable.
I like Disposable and Sharable. They do convey intuition, and allow for names that are distinct from Consumable/Dupable.
On the other hand, they are less discoverable names than ConsumableM and DupableM. Maybe there could be other suggestions? Participants in this thread, would you chime in, and we decide in a few days?
Ah, and I don't think we need to require the
Monadconstraint onDisposable.
We definitely don't need to. And probably shouldn't.