Skip to content

Eq1 / Ord1 deriving again#3207

Merged
garyb merged 6 commits intopurescript:masterfrom
garyb:eq1-deriving-again
Jan 21, 2018
Merged

Eq1 / Ord1 deriving again#3207
garyb merged 6 commits intopurescript:masterfrom
garyb:eq1-deriving-again

Conversation

@garyb
Copy link
Copy Markdown
Member

@garyb garyb commented Jan 20, 2018

Resolves #2702. Much simpler than the previous #2703 😄.

The Eq1 part is done, will do the same for Ord1 now.

@garyb
Copy link
Copy Markdown
Member Author

garyb commented Jan 20, 2018

Brap!

Copy link
Copy Markdown
Member

@kritzcreek kritzcreek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, a few style comments


deriveEq1
:: forall m
. (MonadError MultipleErrors m, MonadSupply m)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These constraints seem unnecessary?


deriveOrd1
:: forall m
. (MonadError MultipleErrors m, MonadSupply m)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

| className == Qualified (Just dataEq) (ProperName "Eq1")
= case tys of
[ty] | Just (Qualified mn' _, _) <- unwrapTypeConstructor ty
, mn == fromMaybe mn mn'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe True (== mn) mn' ?

I was a little confused there for a second :D There's also the more obscure all (== mn) mn' but I think that's too cute :D

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just copied exactly the form of the other matches here. There's some other cleaning up I'd like to do actually, but didn't want to mix it in this PR 😉 so I can change it, but maybe it'd be better to keep them consistent for now?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should've looked at the whole file 🤦‍♂️

| className == Qualified (Just dataOrd) (ProperName "Ord1")
= case tys of
[ty] | Just (Qualified mn' _, _) <- unwrapTypeConstructor ty
, mn == fromMaybe mn mn'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above

@garyb
Copy link
Copy Markdown
Member Author

garyb commented Jan 21, 2018

As evidenced by de9e5ac, this is actually a breaking change, since some things will require a constraint like Eq1 f rather than Eq (f a) when deriving now. I think that's fine though, since they're basically equivalent, and this is for 0.12 anyway.

@kritzcreek
Copy link
Copy Markdown
Member

Do you think we can detect these cases and suggest the usage of Eq1?

@garyb
Copy link
Copy Markdown
Member Author

garyb commented Jan 21, 2018

I think the standard error message does a decent job of that anyway?

No type class instance was found for
                          
            Data.Eq.Eq1 f2

@kritzcreek
Copy link
Copy Markdown
Member

If we can confirm that we can derive Eq1 for the type in question, I'd prefer us to add a hint to the error message:

The missing instance can be derived like:

`derive instance Eq1 TypeInQuestion`

@garyb
Copy link
Copy Markdown
Member Author

garyb commented Jan 21, 2018

The "type in question" is f a though, so we can't suggest deriving an instance for it like that.

The change is that now whenever attempting to derive Eq, if there's a type like (f _) in the current type, it will use eq1 for those values instead of eq, imposing an Eq1 f constraints rather than an Eq (f _) constraint as it would previously. It's just a case of juggling the constraints on the instance. If the _ is also a type variable, then it'll impose Eq _ too, or require that the type is Eq if it's concrete. For example:

Constructor Original required constraints New required constraints
Foo (f a) Eq (f a) Eq1 f, Eq a
Bar (f Int) Eq (f Int) Eq1 f

@kritzcreek
Copy link
Copy Markdown
Member

Just thinking out loud here, does that mean that all our derived Eq instances that involve a type constructor get "slower" because of the indirection from Eq1 dictionary => Eq dictionary.

@garyb
Copy link
Copy Markdown
Member Author

garyb commented Jan 21, 2018

It doesn't apply to type constructors, only applied-type-variables. It's a pretty rare case most likely :)

@kritzcreek
Copy link
Copy Markdown
Member

Well okay, if it's such a rare case I'm not too worried.

@garyb
Copy link
Copy Markdown
Member Author

garyb commented Jan 21, 2018

I'll merge this too if there are no other issues with it?

@kritzcreek
Copy link
Copy Markdown
Member

Go for it! 🎉

@garyb garyb merged commit 4b23171 into purescript:master Jan 21, 2018
@garyb garyb deleted the eq1-deriving-again branch January 21, 2018 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants