#8888 closed bug (fixed)

Document Coercible in user's guide

Reported by: goldfire Owned by:
Priority: normal Milestone: 7.8.1
Component: Documentation Version: 7.8.1-rc2
Keywords: Cc: nomeata
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description

As far as I can tell, there is no discussion of Coercible in the User's Guide. Although the interface to coerce is essentially a vanilla API, the generation of Coercible instances is a language feature, and I believe deserves to be included.

Change History (16)

comment:1 Changed 17 months ago by simonpj

I think you are right. Joachim, how do you feel about this? Obviously include a link to the paper

comment:2 Changed 17 months ago by nomeata

I still believe there is little to be gained by spreading documentation across different places. The user guide already references the API documentation, AFAIR, and the API docs should contain everything (in concise form) the user needs to know. A link to the paper should be added to the API docs...

Hmm, I thought I added a reference to the docs at http://www.haskell.org/ghc/docs/7.8.1-rc2/html/users_guide/special-ids.html. That would be the natural place for a link to the API, woudln’t it?

comment:3 Changed 17 months ago by simonpj

Well, there really is a new form of constraint, written (Coercible s t). It isn't really a class constraint, although by design it behaves in analogous ways. But you can't declare instances of Coercible, and it has special constraint-solving rules all of its own. That sounds like a language extension to me! There is no new syntax, but there is a new sort of constraint.

I think it deserves its own section in Chapter 7. That's where users will lok.

As to "spreading the documentation around", where (apart from the paper) are the solving rules for Coercible given? Perhaps with the (data type!) Corecible in GHC.Types? I'd be happier with a reference from there to the user manual, I think.

Mind you, I'm puzzled. Data.Coerce in package base imports Coercible from GHC.Prim (which has no corresponding Haskell module). But GHC.Types in package ghc-prim defines Coercible (as a data type). So where is it defined? In GHC.Prim or GHC.Types? The Name defined in PrelNames suggests the latter.

Also oddly, PrelNames defines gHC_COERCIBLE which seems to be unused ... delete?

comment:4 Changed 17 months ago by nomeata

Now that we have rc builds with documentation, I can actually point you to the docs (we don’t have that for HEAD):

http://www.haskell.org/ghc/docs/7.8.1-rc2/html/libraries/base-4.7.0.0/Data-Coerce.html

I think it deserves its own section in Chapter 7. That's where users will look.

I doubt that – I find my documentation via hoogle or hayoo, or via the package index. It would also work much better for those who use an IDE like leksah, who have the haddock documentation for each identifier at their finger tip, but possibly not the users guide.

Also note that for example the documentation of, for example, unsafeCoerce has actually been removed from the users guide ([7ea4966]). Isn’t that also a language extension?

But this is bikeshedding and I’m not insisting, so I can move the documentation later today.

But GHC.Types in package ghc-prim defines Coercible (as a data type). So where is it defined? In GHC.Prim or GHC.Types?

The definition in GHC.Types is just so that the constructor has an info table and so on. I had problems using it from GHC.Types (with the overwritten id from PrelNames). I was following the example set by data (~) a b = Eq# ((~#) a b), but if that is wrong I’ll happily learn what the right way would have been.

Also oddly, PrelNames defines gHC_COERCIBLE which seems to be unused ... delete?

Yes, cruft from earlier iterations. Removed.

comment:5 Changed 17 months ago by simonpj

You've put a lot of work into this, and you may well be right. I'd welcome opinions from others.

For now, though, even if the main documentation stays in the library Haddock stuff, could you

  • add a link to the paper (which gives far more background) to the Haddock docs
  • add a user-manual sub-section that summarises in one paragraph and points off to the Haddock docs

That way people like me who look at the manual will still end up in the right place.

I'm still puzzled about two things though.

  • Data.Coerce has
    import GHC.Prim (coerce, Coercible)
    
    But GHC.Prim does not export Coercible.... it's defined in GHC.Types. So how does this even compile?
  • In the Haddock link you sent, Coercible shows as a class. But it's defined (in GHC.Types as a data type. I believe that happens by way of TysWiredIn.coercibleTyCon and coercibleClass, but it's quite hard to unravel, and definitely deserves a Note in GHC.Types, and or TysWiredIn (details in one place, a pointer in the other. It may well be that the way that (~) is handled needs similar documentation.

Simon

comment:6 Changed 17 months ago by nomeata

I'd welcome opinions from others.

Me too.

Adding the cross-references you mention makes perfect sense, will do it in a moment.

So how does this even compile?

coercibleTyCon is added to ghcPrimExports in PrelInfo.

I recall that when I was exporting it from GHC.Types, haddock would display it as a regular data type, not as a constraint.

I now added this note:

Note [Kind-changing of (~) and Coercible]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

(~) and Coercible are tricky to define. To the user, they must appear as
constraints, but we cannot define them as such in Haskell. But we also cannot
just define them only in GHC.Prim (like (->)), because we need a real module
for them, e.g. to compile the constructor's info table.

Furthermore the type of MkCoercible cannot be written in Haskell (no syntax for
~#R).

So we define them as regular data types in GHC.Types, but do /not/ export them.
This ensures we have a home module. We then define them with the types and
kinds that we actually want, in TysWiredIn, and export them in GHC.Prim.

Haddock still takes the documentation from GHC.Types (and not from the fake
module created from primops.txt.pp), so we have the user-facing documentation
here.

comment:7 Changed 17 months ago by simonpj

"coercibleTyCon is added to ghcPrimExports in PrelInfo". Wow! That is truly unique! Coercible is defined and exported (in the interface file) by GHC.Types, and is exported by GHC.Prim. I can imagine all sorts of confusion can arise from that. I'm astonished it works. And, despite its unique weirdness, there is no comment with ghcPrimExports.

None of this happens for (~). Why it needed for Coercible?

After all, it's in the wiredInTyCons in TysWiredIn. Why does it also need to be in ghcPrimExports at all? Why not just remove it? (And import it from GHC.Types in Data.Coerce). There may be some Deep Reason for all this strangeness, but I can't see it.

comment:8 Changed 17 months ago by nomeata

And, despite its unique weirdness, there is no comment with ghcPrimExports.

Added. ([d53ccab])

None of this happens for (~). Why it needed for Coercible?

Hmm. Good question. I believe that (~) needs to not to be importable at all (it is handled by the Parser). Also commented in the Note. ([b19daeb])

There may be some Deep Reason for all this strangeness, but I can't see it.

It is just what happened to work and seems reasonable, starting with the example of (~). Quite likely that a less strange implementation is possible (with little change to make sure haddock and ghci use the updated kind); I do not know my way around all related parts of the compiler yet.

Last edited 17 months ago by nomeata (previous) (diff)

comment:9 Changed 17 months ago by Joachim Breitner <mail@…>

In 1e36a386042248523de69ad6b02c43a6631ed5d0/ghc:

Document Coercible in the user guide

as a subsection of "Equality constraints", containing references to the
module's haddock and to the paper. Fixes #8888

comment:10 Changed 17 months ago by Joachim Breitner <mail@…>

In fc7aaf57a33ab07b70628c75fcf134fdf4e701e5/ghc-prim:

Refer to the coercible paper in Coercible' docs

Implements parts of #8888.

comment:11 Changed 17 months ago by nomeata

  • Status changed from new to merge

References from user guide to haddock, and from both to the paper added. I guess we want this to be merged into 7.8.

comment:12 Changed 17 months ago by simonpj

The example of (~) doesn't have one type constructor claiming to be defined in two different modules! What you are doing here is totally new, and does not follow any previous pattern.

To be specific: what goes wrong if you simply remove Coercible from ghcPrimExports?

comment:13 follow-up: Changed 17 months ago by nomeata

To be specific: what goes wrong if you simply remove Coercible from ghcPrimExports?

It cannot be imported any more.

And if I export it in GHC.Types and import it from there, then haddock and ghci (IIRC) display it as regular data type, not as a constraint, which I found very confusing. This might be a considered a bug or a misfeature; should I open a bug for it?

comment:14 in reply to: ↑ 13 Changed 17 months ago by simonpj

Replying to nomeata:

And if I export it in GHC.Types and import it from there, then haddock and ghci (IIRC) display it as regular data type, not as a constraint,

Are you certain of that? Since it is in wiredInTyCons it will never get into GHC/Types.hi, nor will it be read from the interface file, so GHCi could never know that in the source file it was declared with data.

comment:15 Changed 17 months ago by nomeata

Are you certain of that? Since it is in wiredInTyCons it will never get into GHC/Types.hi, nor will it be read from the interface file, so GHCi could never know that in the source file it was declared with data.

I am relatively certain, but didn’t try it out right now. I just opened a bug about it: #8894, maybe I’ll work on it when I have some quiet minutes, but not right now.

comment:16 Changed 17 months ago by thoughtpolice

  • Resolution set to fixed
  • Status changed from merge to closed

Merged in 7.8.

Note: See TracTickets for help on using tickets.