New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Design for dataToTag# #104
Comments
I don't have any thoughts on your question. However, I do have thoughts about the class, because of some work I was doing recently. In particular, it would be nice to have one or two associated types, and probably another method:
|
Is it backwards-compatible? That means that everywhere a user can successfully compile myDataToTag :: forall (a :: Type). a -> Int#
myDataToTag = dataToTag# That compiles today. Will it compile after this change? I doubt it. But have I missed something here? |
Ah, you are right. Of course: So, fair cop: it's not backward compatible if you write over-polymorphic functions involving |
What about newtype wrappers of various sorts? Will |
Can you give concrete examples of what you mean? DItto for your earlier suggestions, not all of which I could parse. Thanks! |
@simonpj |
|
The newtype question: today we can apply A symmetry question: I don't see a |
I just discovered that |
Can I ask: does the CLC see If the former, we are totally open for the CLC's guidance. Eg. no |
I see. To spell it out, given
is Today I think the answer is "yes it is well typed", and would return the tag on the enclosed Bool. I don't know if that's what you want, and would welcome the CLC's guidance. It's a good question. We can implement either behaviour I think; but rejecting the above is certainly easier. Accepting it would lead to more design questions like "what if the data constructor is not in scope". My instinct to make a conservative choice now (reject), and loosen up later if we find compelling applications. |
There will certainly be a |
Hmm. I'm not convinced. Can you show some compelling examples? I suspect you'll quickly need the Data class anyway if you want to do anything polymorphic. Currently |
It's kinda borderline, but I'm inclined to say that it's in scope for CLC because of a new type class. |
@simonpj could you please elaborate why do you need a type class? Could we just have |
What I actually wanted to use this for, that would require more changes to work:
type DMap :: (k -> Type) -> (k -> Type) -> Type which is basically the same as |
I don't think |
Well, Does breaking parametricity matter? Well, foldr/build fusion becomes unsound.
|
I have no idea if this is true, but are there perhaps other functions in the future that might also be interested in this? If so, that suggests maybe the type class you want (or perhaps even just a built in I may well be picking bike shed paint colours out before we've even got the bike shed, though. |
|
@Ericson2314 the situation is as follows:
@simonpj how magical is the proposed new type class? Can users define their own instances? |
Once again I ask: what is the criterion you are using here. I am super keen to have a clear criterion for
I am really keen to know! You clearly have a criterion @Bodigrim: can you say what it is? Talking of "core type classes" is just not precise. Is I think your implicit criterion may be:
Let's review your bullets in the light of this proposed definition:
So, is that the definitino? And if not, what is the definition? Thanks! Clearing this up once and for all would be incredibly helpul |
Here is an example of a criterion that might work:
This "internal modules" convention is widely and successfully used in the Haskell ecosystem. [EDIT: corrected |
For (Separately, I though the widely-used convention was |
Oh, I beg your pardon, yes. I'll amend my post. |
That might be rather misleading, since there are plenty of modules exported from the
I agree that renaming |
Are there? Most stuff comes through Prelude, or Data.List, or Control.Monad etc. What things do you have in mind? And if there are, would it not be better to export them through some more "blessed" module name?
That is one possibility. It has the disadvantage that one has to know the list ot stable modules -- you can't tell from their names. But that's just my opinion. I am entirely content to submit to the Will of the CLC, if the CLC can come to a view on the matter. Thanks for contributing to the dialogue! |
Sorry for my late arrival here. I have several remarks:
I included some discussion about this in (the current draft of) the overview note for the MR, which I have reproduced here for convenience.
Similar reasoning to point 2b also means that uses of {-# LANGUAGE MagicHash #-}
import GHC.Exts (Int(..), dataToTag#)
main :: IO ()
main = print (I# (dataToTag# flip)) Running interactively or compiling with
Correct: This code is currently OK but will fail to typecheck after
The most compelling use for
Rather magical: Users cannot define their own instances. (I suppose that since
There is one un-answered question about the current implementation's interaction with backpack, and there are a few other non-essential tasks I'd like to take care of before merging. But the implementation is basically complete! Here's a quick run-down of the basic user-facing design questions, and how the current implementation answers them:
|
I'm talking about the GHC API, which is a collection of modules exposed from the |
Aha. I was talking exclusively about the |
@Bodigrim: I have pushed a commit reverting the unrelated primop type changes. I also bumped the version number to 9.2.100 just to make a stale-interfaces issue less likely. (I really hope that's the cause of the |
@clyring this looks better. But could you please ensure that your branch is atop of 9.2.5? It seems to suffer from https://gitlab.haskell.org/ghc/ghc/-/issues/21964. I'm on M2. |
The branch does contain the fix for that issue (74ca6191fa0), which is currently still the last commit in the ghc-9.2 branch. |
Sigh. I switched to my old, x64 machine and happy to tell that the change does not seem to affect any Stackage packages, which is good.
@clyring could you confirm that your comment remains up-to-date with the most recent developments and there were no design changes? |
I'm surprised there's no breakage in clc-stackage. Yes, that comment remains up-to-date. |
Dear CLC members, let's vote on the proposal to replace GHC.Exts.dataToTag# :: forall (a :: Type). a -> Int# with type DataToTag :: forall {lev :: Levity}. TYPE (BoxedRep lev) -> Constraint
class DataToTag a where
dataToTag# :: a -> Int# as detailed in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/8912. The motivation for the change is in the first half of #104 (comment). The final user-facing design is described in #104 (comment). In theory, as explained in #104 (comment), this is a breaking change, but practically no package in +1 from me. |
+1 |
-1 (would change to +1 if we don't expose The net effect of this proposal on CLC-land (i.e.
1 seems fine. Although this is an implementation detail which probably have never been exposed from |
Tom as I understand it, you want to expose
That is, the same names as before, but with (The inconsistent naming is a wart, but perhpas one that the CLC thinks that the costs of making it consistent exceed the benefits?) Naming aside though, can you do that without exposing the
So I must be able to import |
I'm saying that both Since Does that help? |
Aha, thank you. That is indeed clearer. Two thoughts. First.
If that's what the CLC wants then fine. But I think that many people entirely uninterested in GHC's implementation will want If the CLC wants to remove it from Second
That might be difficut, because Since the CLC's wish is that the external (stable) API of |
I'm just speaking for myself here. The CLC makes decisions by majority vote. Whether that leads to the CLC "wanting" something, or to coherent long-range policy, is an open question. But it is about the maximum the CLC has the bandwidth for at the moment.
It exposes the implementation detail that GHC chooses to represent constructors with integers assigned in a particular way, and it works on the assumption that this assignment is stable across compiler invocations and also across compiler versions. It's not the deepest magic ever but it does seem deep magic enough that I'm wary of seeing it exposed from
Sure, because normally packages expose functions that people are supposed to use.
But your MR already exposes them from
Exposing To reiterate, this is my personal opinion, not a coherent policy, certainly not CLC policy. Other CLC members may disagree with what I have written here. To help improve the situation in future, regardless of the outcome of this proposal, I think it would be valuable to try to form a coherent policy for |
I would warmkly welcome such a policy, thank you. |
OK yes, that is true. Fine: I think Matthew and I would be open to what the CLC wants. But I suggest that the alternatives are:
We'll await a resolution from CLC. Thanks! |
The advice at the top of
Most of the other modules in |
Yes, I appreciate my point of view on this is unconventional and I don't anticipate others in the CLC agreeing with me. |
+1 |
1 similar comment
+1 |
Thanks all, 4 votes in favour are enough to approve. |
+1 The change in type is certainly an improvement here, as at least as I understand it, one could imagine instances of the DataToTag class being handwritten and nothing being out of the ordinary semantically with the new version of the function, so while I would have been in favour of deprecating and removing the previous getTag, I think the new constrained one is probably fine. |
I'm trying to summarise the state of this proposal as part of my volunteering effort to track the progress of all
Please, let me know if you find any mistakes 🙂 @clyring could you share a status update on the implementation and what are next steps? Also, please do let CLC know if you need any help, so we can coordinate and prioritise approved proposals accordingly! |
The underlying primop has some smelly special-cases and gunk near |
Closes #20532. This implements CLC proposal 104: haskell/core-libraries-committee#104 The design is explained in Note [DataToTag overview] in GHC.Tc.Instance.Class. This replaces the existing `dataToTag#` primop. These metric changes are not "real"; they represent Unique-related flukes triggering on a different set of jobs than they did previously. See also #19414. Metric Decrease: T13386 T8095 Metric Increase: T13386 T8095 Co-authored-by: Simon Peyton Jones <simon.peytonjones@gmail.com>
The merge request !8912 implementing this proposal has finally landed. These changes will appear in base-4.20.0, shipped with ghc-9.10. |
Matthew and I would like to consult you about the API exposed to users of
base
for thedataToTag#
operator.Currently we have a primop
and a strangely named alias in GHC.Base
Of course this is all wrong:
dataToTag#
is way too polymorphic: it can't possibly work for every typedataToTag#
are to data types; but it's a fragile check,.So Matthew is fixing that by introducing
That fixes both things at one blow:
dataToTag#
now has a type class constrained type, so it's not over-polymoprhicSo 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 defineas wrappers for
dataToTag#
that return a civilised boxed Int. It would be nice to make these levity-polymorphic too, but you can't writebecause there is a levity-polymorphic binder
x
.An alternative would be to put dataToTag into the class like this
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'The text was updated successfully, but these errors were encountered: