Skip to content

Fix TH bug when deriving ToJSON1/2 or FromJSON1/2 for types that don't mention the parameter #455

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

Merged
merged 3 commits into from
Jul 27, 2016

Conversation

RyanGlScott
Copy link
Member

Before, this code:

newtype Foo a = Foo (Foo Int)

$(deriveToJSON  defaultOptions ''Foo)
$(deriveToJSON1 defaultOptions ''Foo)

Would generate the following ToJSON1 instance:

    deriveToJSON1 defaultOptions ''Foo
  ======>
    instance ToJSON1 Foo where
      liftToJSON
        = \ _tj1_aFns _tjl1_aFnt value_aFnr
            -> case value_aFnr of {
                 Foo arg1_aFnu -> liftToJSON toJSON toJSONList arg1_aFnu }
      liftToEncoding
        = \ _te1_aFnw _tel1_aFnx value_aFnv
            -> case value_aFnv of {
                 Foo arg1_aFny
                   -> liftToEncoding toEncoding toEncodingList arg1_aFny }

Although this typechecks, actually contradicts the strategy that GHC adapts when deriving * -> *-kinded classes (e.g., Functor). Namely, when an argument type doesn't mention the last type parameter at all, GHC doesn't attempt to "tunnel into" the type expression like the above code is doing with the expression liftToJSON toJSON toJSONList.

With the changes in this PR, the generated code would instead be:

    deriveToJSON1 defaultOptions ''Foo
  ======>
    instance ToJSON1 Foo where
      liftToJSON
        = \ _tj1_aFo0 _tjl1_aFo1 value_aFnZ
            -> case value_aFnZ of { Foo arg1_aFo2 -> toJSON arg1_aFo2 }
      liftToEncoding
        = \ _te1_aFo4 _tel1_aFo5 value_aFo3
            -> case value_aFo3 of { Foo arg1_aFo6 -> toEncoding arg1_aFo6 }

@phadej
Copy link
Collaborator

phadej commented Jul 16, 2016

Could you add the test for this? If i understood correctly, liftToJSON undefined undefined (Foo 1) should work, but wasn't working previously?

@RyanGlScott
Copy link
Member Author

Good point - I've added a regression test for this property.

@@ -93,6 +93,9 @@ tests = testGroup "unit" [
, testGroup "Issue #351" $ fmap (testCase "-") issue351
, testGroup "Nullary constructors" $ fmap (testCase "-") nullaryConstructors
, testGroup "FromJSONKey" $ fmap (testCase "-") fromJSONKeyAssertions
, testGroup "PR #455" [
Copy link
Collaborator

Choose a reason for hiding this comment

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

it could be directly testCase "PR #445" pr445, no need to wrap in testGroup

@phadej
Copy link
Collaborator

phadej commented Jul 17, 2016

Except from a minor style issue, LGTM.

@RyanGlScott
Copy link
Member Author

RyanGlScott commented Jul 17, 2016

Good point again, updated.

@bergmark
Copy link
Collaborator

Cool, thanks!

@bergmark bergmark merged commit 29eeac4 into haskell:master Jul 27, 2016
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

Successfully merging this pull request may close these issues.

3 participants