-
Notifications
You must be signed in to change notification settings - Fork 37
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
singletons has nondeterministic type variable orderings #367
Comments
Oof. Good point. I'm not convinced we need to go with something like |
I want to agree with you here, but something doesn't quite sit right with me about this plan. I think the thing that bugs me is the fact that we'd need to change the type of I could (reluctantly) get on board with a quadratic-time algorithm, but going cubic or higher generally indicates to me that whatever approach I'm using is not going to scale at all. It's true that pretty much no test case in I actually don't think it would be that hard to whip up an insert-ordered
True, but that doesn't mean people aren't sensitive to increasing compile times. Take this issue, for example :) |
OK, if you want to cook up the fancy data structure, I won't stop you. As for |
It turns out that there is a Hackage library that's perfect for our needs:
Once the issues above become resolved, we can move forward with this. Alternatively, if we don't want to wait, we could always inline the implementations of |
There were several places in `singletons` that would compute entirely different things depending on the order in which GHC's unique numbers happened to be computed. Like the corresponding `th-desugar` patch (in goldfirere/th-desugar#115), this fixes these issues by swapping out nondeterministic uses of `Map` and `Set` with `th-desugar`'s new `OMap` and `OSet` data structures, which remember the order in which elements were inserted. This patch looks large, but half of the modifications are routine changes brought about by switching data structures, and the other half are test suite wibbles brought about by `singletons` settling on a deterministic order for the expected output. The upshot is that we can finally run the `singletons` test suite with `-dunique-increment=-1` and have it still pass! Hooray! Fixes #367.
There were several places in `singletons` that would compute entirely different things depending on the order in which GHC's unique numbers happened to be computed. Like the corresponding `th-desugar` patch (in goldfirere/th-desugar#115), this fixes these issues by swapping out nondeterministic uses of `Map` and `Set` with `th-desugar`'s new `OMap` and `OSet` data structures, which remember the order in which elements were inserted. This patch looks large, but half of the modifications are routine changes brought about by switching data structures, and the other half are test suite wibbles brought about by `singletons` settling on a deterministic order for the expected output. The upshot is that we can finally run the `singletons` test suite with `-dunique-increment=-1` and have it still pass! Hooray! Fixes #367.
There were several places in `singletons` that would compute entirely different things depending on the order in which GHC's unique numbers happened to be computed. Like the corresponding `th-desugar` patch (in goldfirere/th-desugar#115), this fixes these issues by swapping out nondeterministic uses of `Map` and `Set` with `th-desugar`'s new `OMap` and `OSet` data structures, which remember the order in which elements were inserted. This patch looks large, but half of the modifications are routine changes brought about by switching data structures, and the other half are test suite wibbles brought about by `singletons` settling on a deterministic order for the expected output. The upshot is that we can finally run the `singletons` test suite with `-dunique-increment=-1` and have it still pass! Hooray! Fixes #367.
It occurred to me recently that the sorts of nondeterminism issues that plagued GHC for years also plague
singletons
. While GHC has fixed these issues,singletons
has not. The following example illustrates the problem well:When a user writes
sConst @Bool
, which type gets instantiated toBool
:a
orb
? You might think "well obviously the answer isa
", and a quick smoke-test in GHCi would appear to confirm that hunch:However, that's only because of a lucky fluke. As it turns out, if you pass
-dunique-increment=-1
to GHC, then you'll get a different answer:Ack. It turns out that the order of the kind variables
a
andb
insConst
's type signature completely depend on which unique values happen to be gensymmed for them (bynewName
) insingletons
' Template Haskell machinery. This is because several functions inth-desugar
andsingletons
collect type variables usingSet Name
, and theOrd Name
instance compares byName
's unique values first and foremost. Ifa
happens to have a smaller unique thanb
, then when you callSet.toList
on a set containing{a, b}
, then you'll get[a,b]
. Ifb
has a smaller unique thana
, on the other hand, then you'll get[b,a]
.Essentially, any place in
singletons
where callS.toList
on aSet Name
(that can affect the user-facing API) should be treated as nondeterministic code. I count at least three places inth-desugar
andsingletons
(each!) where we do this at the time of writing.Luckily, GHC has figured out how to solve this problem, so we should be able to learn from its mistakes. One of the main tricks that GHC uses to avoid this sort of nondeterminism is by switching out uses of
Set
for a deterministic, insert-ordered set, such asUniqDSet
. It seems likely that we'll need to find such a data structure on Hackage (or conjure up one ourselves) and use it throughoutth-desugar
andsingletons
where appropriate.The text was updated successfully, but these errors were encountered: