Skip to content

Design for dataToTag# #104

@simonpj

Description

@simonpj

Matthew and I would like to consult you about the API exposed to users of base for the dataToTag# operator.

Currently we have a primop

dataToTag# :: forall (a :: Type). a -> Int#

and a strangely named alias in GHC.Base

getTag :: forall (a :: Type). a -> Int#
getTag x = dataToTag# x

Of course this is all wrong:

  • dataToTag# is way too polymorphic: it can't possibly work for every type
  • It is levity-monomorphic, so you can't use it on unlifted data types
  • Plus, its implementation is a mess -- there is an ad hoc check that all uses of dataToTag# are to data types; but it's a fragile check,.

So Matthew is fixing that by introducing

type DataToTag :: forall {lev :: Levity}. TYPE (BoxedRep lev) -> Constraint
class DataToTag a where
     dataToTag# :: a -> Int#

That fixes both things at one blow:

  • dataToTag# now has a type class constrained type, so it's not over-polymoprhic
  • Both the class and its operation are levity-polymorphic.
  • The implementation is very nice; no hacks any more.

So far so good: it's a change, but a backward-compatible change.

But we'd also like to kill off the strangely named getTag while we are about it (with a deprecation cycle). And we propose to define

dataToTag :: forall (a :: TYPE LiftedRep). DataToTag a => a -> Int
dataToTag' :: forall (a :: TYPE UnliftedRep). DataToTag a => a -> Int

as wrappers for dataToTag# that return a civilised boxed Int. It would be nice to make these levity-polymorphic too, but you can't write

dataToTag x = I# (dataToTag# x)

because there is a levity-polymorphic binder x.

An alternative would be to put dataToTag into the class like this

class DataToTag a where
     dataToTag# :: a -> Int#
     dataToTag :: a -> Int

and now dataToTag can be levity-monomorphic. But the implementation is significantly more fiddly, because we have to build that dictionary on the fly.

The naming of the unlifted version is up for grabs. I suggested dataToTag' by analogy with foldl'

Metadata

Metadata

Assignees

No one assigned

    Labels

    approvedApproved by CLC votebase-4.20Implemented in base-4.20 (GHC 9.10)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions