Opened 2 years ago

Closed 2 years ago

#10891 closed bug (fixed)

`reify` doesn't find associated type families

Reported by: antalsz Owned by:
Priority: normal Milestone: 8.0.1
Component: Template Haskell Version: 7.10.2
Keywords: type families; newcomer Cc: jstolarek
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s): Phab:D1254
Wiki Page:

Description (last modified by osa1)

Template Haskell's reify doesn't find the the associated type families of a type class. Consider the following two classes:

class C a where
  f :: a -> Int

class C' a where
  type F a :: *
  f' :: a -> Int

These produce identical, up to renaming, output when passed to reify:

-- putStrLn $(stringE . show =<< reify ''C)
ClassI (ClassD [] Ghci1.C [PlainTV a_1627398388] []
               [SigD Ghci1.f
                     (ForallT [PlainTV a_1627398388]
                              [ClassP Ghci1.C [VarT a_1627398388]]
                              (AppT (AppT ArrowT (VarT a_1627398388))
                                    (ConT GHC.Types.Int)))])
       []

-- putStrLn $(stringE . show =<< reify ''C')
ClassI (ClassD [] Ghci3.C' [PlainTV a_1627405973] []
               [SigD Ghci3.f'
                     (ForallT [PlainTV a_1627405973]
                              [ClassP Ghci3.C' [VarT a_1627405973]]
                              (AppT (AppT ArrowT (VarT a_1627405973))
                                    (ConT GHC.Types.Int)))])
       []

If I know the name of F, I can look up information about it:

-- putStrLn $(stringE . show =<< reify ''F)
FamilyI (FamilyD TypeFam
                 Ghci3.F
                 [PlainTV a_1627405973]
                 (Just StarT))
        []

But I can't find the name of F in the first place. Even if I add an instance of the type class, the InstanceD has none of the information about the definition. Given

instance C' [a] where
  type F [a] = a
  f' = length

we get

-- putStrLn $(stringE . show =<< reify ''C')
ClassI (ClassD [] Ghci3.C' [PlainTV a_1627405973] []
               [SigD Ghci3.f'
                     (ForallT [PlainTV a_1627405973]
                              [ClassP Ghci3.C' [VarT a_1627405973]]
                              (AppT (AppT ArrowT (VarT a_1627405973))
                                    (ConT GHC.Types.Int)))])
       [InstanceD []
                  (AppT (ConT Ghci3.C')
                        (AppT ListT (VarT a_1627406161)))
                  []]

This problem was confirmed to exist in the following configurations:

  • GHC 7.10.2 with version 2.10.0.0 of the template-haskell package.
  • GHC 7.8.3 with version 2.9.0.0 of the template-haskell package.
  • GHC 7.4.2 with version 2.7.0.0 of the template-haskell package.

(I also posted this on Stack Overflow in 2013, where it has been languishing ever since: http://stackoverflow.com/q/17247880/237428.)

Change History (16)

comment:1 Changed 2 years ago by goldfire

Keywords: newcomer added; template haskell removed
Milestone: 8.0.1

Well, that's silly. My guess, without looking at the code, that this could be fixed in 2-3 lines. Newcomers?

comment:2 Changed 2 years ago by osa1

Description: modified (diff)

comment:3 Changed 2 years ago by osa1

How should default type instances be reified? e.g. if I have something like:

class C a where
  type T a :: *
  type T a = a

Syntactically it looks like TySynD but semantically it's different.

comment:4 Changed 2 years ago by goldfire

That's true that it's different semantically. But Template Haskell is all about syntax, not semantics. But I'd make it a TySynInstD instead of a TySynD (even though the latter is more syntactically accurate). It seems a bit overwrought to make a new constructor for Dec for this case.

comment:5 Changed 2 years ago by jstolarek

Cc: jstolarek added

comment:6 Changed 2 years ago by osa1

Another question: Normally we don't fill InstanceD contents, probably because we can't anyway -- because we need source code for this, right? But we can still fill information about associated type instances. Should we do this or are there any problems with that? (maybe it's not possible etc.)

(By InstanceD I mean the one generated for ClassI)

comment:7 Changed 2 years ago by osa1

Differential Rev(s): 1254
Owner: set to osa1

comment:8 Changed 2 years ago by goldfire

Differential Rev(s): 1254Phab:1254

That's a good point. If it's easy to do, I think adding the associated type stuff would be nice. But don't go too far out of way to do it. Thanks for jumping in!

comment:9 Changed 2 years ago by osa1

Status: newmerge

comment:10 Changed 2 years ago by osa1

Differential Rev(s): Phab:1254Phab:D1254

comment:11 Changed 2 years ago by Austin Seipp <austin@…>

In 5c115236/ghc:

reify associated types when reifying typeclasses

As reported in Trac #10891, Template Haskell's `reify` was not generating Decls
for associated types. This patch fixes that.

Note that even though `reifyTyCon` function used in this patch returns some
type instances, I'm ignoring that.

Here's an example of how associated types are encoded with this patch:

(Simplified representation)

    class C a where
      type F a :: *

    -->

    OpenTypeFamilyD "F" ["a"]

With default type instances:

    class C a where
      type F a :: *
      type F a = a

    -->

    OpenTypeFamilyD "F" ["a"]
    TySynInstD "F" (TySynEqn [VarT "a"] "a")

Reviewed By: goldfire

Differential Revision: https://phabricator.haskell.org/D1254

GHC Trac Issues: #10891

comment:12 Changed 2 years ago by thomie

Owner: osa1 deleted
Status: mergenew

This commit was reverted in 39a262e53bab3b7cf827fa9f22226da5fca055be.

comment:13 Changed 2 years ago by Ben Gamari <ben@…>

In b4d43b4e/ghc:

reify associated types when reifying typeclasses(#10891)

As reported in Trac #10891, Template Haskell's `reify` was not
generating Decls for associated types. This patch fixes that.

Note that even though `reifyTyCon` function used in this patch returns
some type instances, I'm ignoring that.

Here's an example of how associated types are encoded with this patch:

(Simplified representation)

    class C a where
      type F a :: *

    -->

    OpenTypeFamilyD "F" ["a"]

With default type instances:

    class C a where
      type F a :: *
      type F a = a

    -->

    OpenTypeFamilyD "F" ["a"]
    TySynInstD "F" (TySynEqn [VarT "a"] "a")

Test Plan:
This patch was already reviewed and even merged. The patch is later
reverted because apparently it broke the build some time between the
validation of this patch and merge. Creating this new ticket to fix the
validation.

Reviewers: goldfire, austin, bgamari

Reviewed By: bgamari

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D1277

GHC Trac Issues: #10891

comment:14 Changed 2 years ago by thomie

Should this be merged to 7.10? Or can this ticket be closed?

comment:15 Changed 2 years ago by goldfire

I argue against merging, as it changes an external interface. My TH code dislikes new, unexpected things being reported. :)

If you (whoever reads this next) agree, close the ticket.

comment:16 Changed 2 years ago by rwbarton

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.