Skip to content
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

Type.Row exports both a type and a class called Cons #43

Closed
hdgarrood opened this issue Jan 7, 2019 · 8 comments
Closed

Type.Row exports both a type and a class called Cons #43

hdgarrood opened this issue Jan 7, 2019 · 8 comments

Comments

@hdgarrood
Copy link
Contributor

At the moment, Type.Row re-exports both Prim.Row.Cons and Prim.RowList.Cons. Unfortunately, this will be disallowed at some point in the future (see purescript/purescript#3502 and purescript/purescript#1888), so presumably we will need to remove one of them.

Perhaps we can export a type synonym along the lines of

type ConsRL = Prim.RowList.Cons

so that at least you don't need to separately import Prim.RowList if you were previously using Prim.RowList.Cons via Type.Row.

@hdgarrood
Copy link
Contributor Author

I've come across one problem with this: a type synonym for Prim.RowList.Cons isn't going to be particularly useful, because 99% of the time, you're going to want to use it in instances, where type synonyms are disallowed. Perhaps we should lift the restriction that type synonyms may not appear in instances: purescript/purescript#3391

@LiamGoodacre
Copy link
Member

How about splitting Type.Row into Type.Row and Type.RowList, in the same way that we have Prim.Row and Prim.RowList? Then they are exported from different modules.

@hdgarrood
Copy link
Contributor Author

👍 that sounds sensible to me too.

@joneshf
Copy link
Member

joneshf commented May 26, 2019

There is another way that doesn't require a new type synonym or force any breaking changes. The module only actually exports Prim.RowList.Cons. From the perspective of anyone consuming Type.Row, it has only ever exported Prim.RowList.Cons, no matter what the source code says. Those consumers include Type.Prelude and Type.Row.Homogeneous. If you attempt to import Prim.Row.Cons from Type.Row, you get an UnknownImport error:

module Foo where

import Type.Row (class Cons)
[1/2 UnknownImport] src/Foo.purs:3:18

  3  import Type.Row (class Cons)
                      ^^^^^^^^^^
  
  Cannot import type class Cons from module Type.Row
  It either does not exist or the module does not export it.

If purescript/purescript#3502 is fixed and released it will cause the current version to error, but a non-breaking change can be something like:

diff --git a/src/Type/Row.purs b/src/Type/Row.purs
index 1f9ede7..caba108 100644
--- a/src/Type/Row.purs
+++ b/src/Type/Row.purs
@@ -12,7 +12,8 @@ module Type.Row
   , type (+)
   ) where
 
-import Prim.Row (class Lacks, class Nub, class Cons, class Union)
+import Prim.Row (class Lacks, class Nub, class Union)
+import Prim.Row as Row
 import Prim.RowList (kind RowList, Cons, Nil, class RowToList)
 import Type.Equality (class TypeEquals)
 import Type.Data.Symbol as Symbol
@@ -33,7 +34,7 @@ instance listToRowNil
 
 instance listToCons
   :: ( ListToRow tail tailRow
-     , Cons label ty tailRow row )
+     , Row.Cons label ty tailRow row )
   => ListToRow (Cons label ty tail) row
 
 -- | Remove all occurences of a given label from a RowList

That change could happen today. It doesn't need to wait for the compiler to disallow things.

If a module restructure is still wanted, that's fine, but it's not necessary to address this potential future issue. Please strongly consider making a non-breaking fix for this issue if purescript/purescript#3502 disallows the code.

@hdgarrood
Copy link
Contributor Author

That's a really good point. I agree, let's do that.

@garyb
Copy link
Member

garyb commented May 26, 2019

That's a great find! I'm all for changing the non-breaking way, since functionally it'll be no different.

@hdgarrood
Copy link
Contributor Author

@joneshf would you like to send a PR?

joneshf added a commit to joneshf/purescript that referenced this issue May 26, 2019
As mentioned in the previous commit
(09bfea484ff6e0d77c028f11314763c794df8c47),
we don't want to allow re-exporting a class and a type that have
the same name.
The changes here make that a reality.

The majority of the tests are breaking because we're dependent on
`purescript-typelevel-prelude` and it violates the changes here.
See: purescript/purescript-typelevel-prelude#43
for more information.
@hdgarrood
Copy link
Contributor Author

I am going to close this because this has been addressed by #45, but if anyone feels strongly in favour of adding a Type.RowList module we can reopen this.

hdgarrood added a commit that referenced this issue May 26, 2019
Refs #43, fixes #46.

RowList-related types and classes have been removed from Type.Row and
moved into Type.RowList, in order to prepare for an upcoming compiler
change whereby a module will no longer be allowed to re-export both a
type and a class of the same name; see purescript/purescript#3502
hdgarrood pushed a commit to purescript/purescript that referenced this issue May 26, 2019
* Add failing test for conflicting re-exports (#3502)

Within a module,
we cannot define a class and a data type with the same name.
The issue here is that we can define a class and a data type with
the same name in different modules,
then re-export them both from one module.

We don't want to allow this behavior.
We add a failing test to codify that this should not work.

* Disallow re-exporting same class/type name (#3502)

As mentioned in the previous commit
(09bfea484ff6e0d77c028f11314763c794df8c47),
we don't want to allow re-exporting a class and a type that have
the same name.
The changes here make that a reality.

The majority of the tests are breaking because we're dependent on
`purescript-typelevel-prelude` and it violates the changes here.
See: purescript/purescript-typelevel-prelude#43
for more information.

* Print the type of the conflicting name (#3502)

Before, we only had conflicting exports for the same types of things.
Now that we disallow exports of different types,
we'll want to be a bit more explict in what the problem is.

Errors we'd get before looked like:
```
Export for type B.X conflicts with A.X
```
While that does convey what the problem is, we can do a bit better.

Errors now look like:
```
Export for type B.X conflicts with type class A.X
```

* Update dependencies (#3502)

The changes to `purescript-typelevel-prelude` allow us to pass tests.
The transitive dependency on `purescript-prelude` required an update.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants