-
Notifications
You must be signed in to change notification settings - Fork 502
Add deriveEq for Plinth similar to deriving stock Eq #7433
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
base: master
Are you sure you want to change the base?
Conversation
1bdeaab to
956de09
Compare
Execution Budget Golden Diffoutputplutus-benchmark/cardano-loans/test/9.6/main.golden.eval
plutus-benchmark/coop/test/9.6/certMpBurning.golden.eval
plutus-benchmark/coop/test/9.6/certMpMinting.golden.eval
plutus-benchmark/coop/test/9.6/fsMpBurning.golden.eval
plutus-benchmark/coop/test/9.6/fsMpMinting.golden.eval
plutus-benchmark/linear-vesting/test/9.6/main.golden.eval
plutus-benchmark/nofib/test/9.6/clausify-F5.golden.eval
plutus-benchmark/nofib/test/9.6/knights10-4x4.golden.eval
plutus-benchmark/nofib/test/9.6/queens4-bt.golden.eval
plutus-benchmark/nofib/test/9.6/queens5-fc.golden.eval
plutus-benchmark/script-contexts/test/V3/Data/9.6/purposeIsWellFormed-4.golden.eval
This comment will get updated when changes are made. |
956de09 to
d666dea
Compare
5b30be7 to
5d931a0
Compare
5d931a0 to
396e4e9
Compare
396e4e9 to
97a7b4b
Compare
7593c53 to
3ca2a2e
Compare
SeungheonOh
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too confident in my ability to review TH code. So perhaps a look from @Unisay would be nice. But everything looks right from what I can tell.
| deriveEq ''() | ||
| deriveEq ''(,) | ||
| deriveEq ''(,,) | ||
| deriveEq ''(,,,) | ||
| deriveEq ''(,,,,) | ||
| deriveEq ''(,,,,,) | ||
| deriveEq ''(,,,,,,) | ||
| deriveEq ''(,,,,,,,) | ||
| deriveEq ''(,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,,,,,,,,) | ||
| deriveEq ''(,,,,,,,,,,,,,,,,,,,,,,,,,,) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The great pyramid
|
Also, can you check if this works with polymorphic phantom types? I'm curious as per #4537 |
I will test it out |
Indeed, it does not work with polymorphic phantom types. I don't know yet how to make it work. Unfortunately, it returns me kind the wrong kind |
770689f to
5e72678
Compare
673b24b to
f6a08c0
Compare
Phantom types should work now |
zliu41
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use deriveEq on all the plutus-ledger-api Types?
Good idea |
Add some derived Eq instances
d9a2637 to
d5851d7
Compare
|
|
||
| instance Haskell.Semigroup Value where | ||
| (<>) = unionWith (+) | ||
| instance Haskell.Eq Value where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zliu41 Some cleanup along the way, and use a single implementation between PlutusTx && Haskell
| -- MAYBE: get rid of these and switch to deriving stock, when deriveOrd is merged | ||
| instance Eq a => Haskell.Eq (Extended a) where | ||
| (==) = (PlutusTx.==) | ||
|
|
||
| -- MAYBE: get rid of these and switch to deriving stock, when deriveOrd is merged |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be changed to stock deriving when deriveOrd PR is merged
| instance Haskell.Eq Value where | ||
| (==) = (PlutusTx.==) | ||
|
|
||
| instance Semigroup Value where | ||
| instance PlutusTx.Semigroup Value where | ||
| {-# INLINEABLE (<>) #-} | ||
| (<>) = unionWith (+) | ||
|
|
||
| instance Haskell.Monoid Value where | ||
| mempty = Value Map.empty | ||
| instance Haskell.Semigroup Value where | ||
| (<>) = (PlutusTx.<>) | ||
|
|
||
| instance Monoid Value where | ||
| instance PlutusTx.Monoid Value where | ||
| {-# INLINEABLE mempty #-} | ||
| mempty = Value Map.empty | ||
|
|
||
| instance Haskell.Monoid Value where | ||
| mempty = PlutusTx.mempty | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same cleanup and sharing between implementations
| -- FIXME: need deriveOrd to be merged to add this | ||
| -- deriveEq ''TxInfo | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed because we have inside the datatype Maps, and keys to Maps need an Ord instance. I think it would be easier if we have the ord pr apply these changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is different, we don't have Eq AssocMap instances because of problem with duplicated entries
|
@zliu41 Can you take a look at the last commit only? |
dd788a1 to
ce324dd
Compare
dd788a1 to
a00cb11
Compare
|
|
||
| {-| derive a PlutusTx.Eq instance for a datatype/newtype, similar to Haskell's `deriving stock Eq`. | ||
| One shortcoming compared to Haskell's deriving is that you cannot `PlutusTx.deriveEq` for polymorphic phantom types. -} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation claims you cannot derive for polymorphic phantom types, but PhantomADT test demonstrates it does work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a public function, it would make sense to better document limitations, etc:
{-| Derive a PlutusTx 'Eq' instance for a datatype or newtype.
Similar to Haskell's @deriving stock Eq@, this generates structural equality
with short-circuit evaluation and INLINEABLE pragmas for optimal on-chain performance.
__Usage:__
@
data MyType = Con1 Integer | Con2 Bool
deriveEq ''MyType
@
__Generated code:__
* Pattern-matching clauses for each constructor
* Short-circuit evaluation (stops at first inequality)
* @INLINEABLE@ pragma for cross-module optimization
* Proper handling of phantom type parameters
__Supported types:__
* Regular datatypes with any number of constructors
* Newtypes
* Types with phantom type parameters
* Types with strict or lazy fields
__Unsupported:__
* GADTs (may produce type errors)
* Type families (not tested)
See 'PlutusTx.Eq.Class.Eq' for the class definition.
-}
deriveEq :: Name -> Q [Dec]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation claims you cannot derive for polymorphic phantom types, but PhantomADT test demonstrates it does work?
Forgot to clean the comment. Phantom types do work now.
| ( clause | ||
| [conP name (fmap varP argsL), conP name (fmap varP argsR)] | ||
| ( normalB $ | ||
| case fields of | ||
| [] -> conE 'True | ||
| _ -> | ||
| foldr1 (\e acc -> infixE (pure e) (varE '(&&)) (pure acc)) $ | ||
| zipWith | ||
| ( \argL argR -> | ||
| infixE (pure $ varE argL) (varE '(==)) (pure $ varE argR) | ||
| ) | ||
| argsL | ||
| argsR | ||
| ) | ||
| [] | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant brackets:
| ( clause | |
| [conP name (fmap varP argsL), conP name (fmap varP argsR)] | |
| ( normalB $ | |
| case fields of | |
| [] -> conE 'True | |
| _ -> | |
| foldr1 (\e acc -> infixE (pure e) (varE '(&&)) (pure acc)) $ | |
| zipWith | |
| ( \argL argR -> | |
| infixE (pure $ varE argL) (varE '(==)) (pure $ varE argR) | |
| ) | |
| argsL | |
| argsR | |
| ) | |
| [] | |
| ) | |
| clause | |
| [conP name (fmap varP argsL), conP name (fmap varP argsR)] | |
| ( normalB $ | |
| case fields of | |
| [] -> conE 'True | |
| _ -> | |
| foldr1 (\e acc -> infixE (pure e) (varE '(&&)) (pure acc)) $ | |
| zipWith | |
| ( \argL argR -> | |
| infixE (pure $ varE argL) (varE '(==)) (pure $ varE argR) | |
| ) | |
| argsL | |
| argsR | |
| ) | |
| [] |
| ### Added | ||
|
|
||
| - A `deriveEq` command to derive PlutusTx.Eq instances for datatypes/newtypes, similar to Haskell's | ||
| `deriving stock Eq` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ### Added | |
| - A `deriveEq` command to derive PlutusTx.Eq instances for datatypes/newtypes, similar to Haskell's | |
| `deriving stock Eq` | |
| ### Added | |
| - A `deriveEq` Template Haskell function to automatically derive PlutusTx.Eq instances | |
| for datatypes and newtypes, similar to Haskell's `deriving stock Eq`. | |
| Usage: `PlutusTx.deriveEq ''MyType` | |
| This generates short-circuiting equality checks with proper INLINEABLE pragmas for | |
| optimal on-chain performance. |
| runTestNested | ||
| ["test", "Eq", "Golden"] | ||
| [ $(goldenCodeGen "SomeLargeADT" (deriveEq ''SomeLargeADT)) | ||
| , $(goldenCodeGen "PhantomADT" (deriveEq ''PhantomADT)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mind adding tests for newtypes and records with fields?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, do you know if (self/manually)-recursive types are supported? Would be nice to have a comment (if not) or tests (if yes)
|
|
||
| instance P.Ord Rational where | ||
| {-# INLINEABLE compare #-} | ||
| compare (Rational n d) (Rational n' d') = P.compare (n P.* d') (n' P.* d) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why is compare the only function removed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will take a look at this
Pre-submit checklist: