[Proposal] Unify various specialized mkWeak functions in base?

Hi everyone, In System.Mem.Weak we have an mkWeak function to create weak pointers. But we also have a lot of specialized mkWeak* functions, e.g. mkWeakIORef, mkWeakThreadId, etc, to ensure that we actually pass the unlifted closure instead of the lifted one as the key to the underlying mkWeak# primop. The various specialized mkWeak* functions' signatures don't have a coherent style. Some functions like mkWeakIORef always take a Haskell finalizer argument, while mkWeakThreadId doesn't take a finalizer argument at all. This is troublesome for users since: * Sometimes a user doesn't want to attach a finalizer at all. They could pass a "pure ()" dummy finalizer, but that'll still come with a minor bit of extra runtime overhead * For mkWeakThreadId, they may want to attach a finalizer. The runtime supports it, but the type signature doesn't say so. Of course, they can always add a few extensions and call mkWeak# as they wish, but it would be nicer if we have a uniform API to allow a Haskell finalizer to be added optionally. The simplest API could be something like (forgive my terrible naming): class WeakKey k where mkWeakWithRealKey :: WeakKey k => k -> v -> Maybe (IO ()) -> IO (Weak v) The WeakKey class is just a way of exposing the unlifted field from a single datacon wrapper type, and I think this can be useful for other purposes as well, so maybe we can do something like: class Unlift a where type Unlifted a :: TYPE 'UnliftedRep unlift :: a -> Unlifted a mkWeakWithRealKey :: Unlift k => k -> v -> Maybe (IO ()) -> IO (Weak v) Thanks for reading so far, what are your thoughts on this? The proposed extended interfaces can be easily implemented in 3rd-party packages, but it would be nice to add to base. Cheers, Cheng Shao

You should look at the primitive-unlifted package which offers a class for
wrapping and unwrapping unlifted things and functions for making weak
pointers from (and to) unlifted things.
On Wed, Nov 11, 2020, 4:34 PM Cheng Shao
Hi everyone,
In System.Mem.Weak we have an mkWeak function to create weak pointers. But we also have a lot of specialized mkWeak* functions, e.g. mkWeakIORef, mkWeakThreadId, etc, to ensure that we actually pass the unlifted closure instead of the lifted one as the key to the underlying mkWeak# primop.
The various specialized mkWeak* functions' signatures don't have a coherent style. Some functions like mkWeakIORef always take a Haskell finalizer argument, while mkWeakThreadId doesn't take a finalizer argument at all. This is troublesome for users since:
* Sometimes a user doesn't want to attach a finalizer at all. They could pass a "pure ()" dummy finalizer, but that'll still come with a minor bit of extra runtime overhead
* For mkWeakThreadId, they may want to attach a finalizer. The runtime supports it, but the type signature doesn't say so.
Of course, they can always add a few extensions and call mkWeak# as they wish, but it would be nicer if we have a uniform API to allow a Haskell finalizer to be added optionally. The simplest API could be something like (forgive my terrible naming):
class WeakKey k where mkWeakWithRealKey :: WeakKey k => k -> v -> Maybe (IO ()) -> IO (Weak v)
The WeakKey class is just a way of exposing the unlifted field from a single datacon wrapper type, and I think this can be useful for other purposes as well, so maybe we can do something like:
class Unlift a where type Unlifted a :: TYPE 'UnliftedRep unlift :: a -> Unlifted a
mkWeakWithRealKey :: Unlift k => k -> v -> Maybe (IO ()) -> IO (Weak v)
Thanks for reading so far, what are your thoughts on this? The proposed extended interfaces can be easily implemented in 3rd-party packages, but it would be nice to add to base.
Cheers, Cheng Shao _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Thanks, David! That looks exactly like what I have in mind. Given its
dependency on primitive and primitive not being a part of base (or a boot
lib), I think I'd better give up upstreaming the idea and simply use that
package when really needed.
On Wed, Nov 11, 2020 at 10:36 PM David Feuer
You should look at the primitive-unlifted package which offers a class for wrapping and unwrapping unlifted things and functions for making weak pointers from (and to) unlifted things.
On Wed, Nov 11, 2020, 4:34 PM Cheng Shao
wrote: Hi everyone,
In System.Mem.Weak we have an mkWeak function to create weak pointers. But we also have a lot of specialized mkWeak* functions, e.g. mkWeakIORef, mkWeakThreadId, etc, to ensure that we actually pass the unlifted closure instead of the lifted one as the key to the underlying mkWeak# primop.
The various specialized mkWeak* functions' signatures don't have a coherent style. Some functions like mkWeakIORef always take a Haskell finalizer argument, while mkWeakThreadId doesn't take a finalizer argument at all. This is troublesome for users since:
* Sometimes a user doesn't want to attach a finalizer at all. They could pass a "pure ()" dummy finalizer, but that'll still come with a minor bit of extra runtime overhead
* For mkWeakThreadId, they may want to attach a finalizer. The runtime supports it, but the type signature doesn't say so.
Of course, they can always add a few extensions and call mkWeak# as they wish, but it would be nicer if we have a uniform API to allow a Haskell finalizer to be added optionally. The simplest API could be something like (forgive my terrible naming):
class WeakKey k where mkWeakWithRealKey :: WeakKey k => k -> v -> Maybe (IO ()) -> IO (Weak v)
The WeakKey class is just a way of exposing the unlifted field from a single datacon wrapper type, and I think this can be useful for other purposes as well, so maybe we can do something like:
class Unlift a where type Unlifted a :: TYPE 'UnliftedRep unlift :: a -> Unlifted a
mkWeakWithRealKey :: Unlift k => k -> v -> Maybe (IO ()) -> IO (Weak v)
Thanks for reading so far, what are your thoughts on this? The proposed extended interfaces can be easily implemented in 3rd-party packages, but it would be nice to add to base.
Cheers, Cheng Shao _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
participants (2)
-
Cheng Shao
-
David Feuer