linear-base icon indicating copy to clipboard operation
linear-base copied to clipboard

Dispose with side effects

Open pedromsrocha opened this issue 3 years ago • 9 comments

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.

pedromsrocha avatar Jan 17 '23 15:01 pedromsrocha

Why not be more general?

class Monad m => Disposable m a where
  dispose :: a %1 -> m ()

treeowl avatar Jan 17 '23 15:01 treeowl

I'm always in favour of general solutions, so agree! 😃

pedromsrocha avatar Jan 17 '23 15:01 pedromsrocha

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.

aspiwack avatar Jan 20 '23 09:01 aspiwack

Which order should the class parameters go in? I can't decide which partial application seems more likely.

treeowl avatar Jan 20 '23 09:01 treeowl

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.

aspiwack avatar Jan 20 '23 10:01 aspiwack

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 avatar May 20 '23 21:05 alt-romes

@alt-romes PR still welcome :slightly_smiling_face: .

aspiwack avatar May 22 '23 10:05 aspiwack

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.

alt-romes avatar May 22 '23 10:05 alt-romes

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 Monad constraint on Disposable.

We definitely don't need to. And probably shouldn't.

aspiwack avatar May 22 '23 12:05 aspiwack