Skip to content

[#737] Add `HasRPCRepr` typeclass

Diogo Castro requested to merge diogo/#737-has-rpc-repr into master

Description

Problem: The AsRPC type family has an unenforced law:

ToT (AsRPC t) ~ AsRPC (ToT t)

This law basically ensures that ToT and AsRPC are commutative

   Storage ----------(applying ToT)-------------> ToT Storage
      |                                                |
      |                                                |
      |                                                |
(applying AsRPC)                                (applying AsRPC)
      |                                                |
      |                                                |
      |                                                |
      |                                                V
      |                                        AsRPC (ToT Storage)
      V                                                ~
AsRPC Storage ------(applying ToT)-----------> ToT (AsRPC Storage)

This, in turn, means you can go from some type Storage to AsRPC Storage by composing fromVal . valueAsRPC . toVal:

   Storage ------------(toVal)--------------> Value (ToT Storage)
      |                                                |
      |                                                |
      |                                                |
(fromVal . valueAsRPC . toVal)                    (valueAsRPC)
      |                                                |
      |                                                |
      |                                                |
      |                                                V
      |                                   Value (AsRPC (ToT Storage))
      V                                                ~
AsRPC Storage <--------(fromVal)--------- Value (ToT (AsRPC Storage))

This law is not enforced by the type system, though we do have some smoke tests in Test.AsRPC.

However, in #737 (closed), we will need to make use of this law, so we need to formalize it and enforce it.

Solution:

  1. Wrap the AsRPC type family in a HasRPCRepr typeclass.
  2. We can now add this law as a superclass of HasRPCRepr, therefore enforcing it.

The kind signature of the AsRPC type family is AsRPC :: k -> k. It is polykinded because we need it to work for kinds T and Type.

However, this law only holds for Type, not for T. Therefore, we had to split the AsRPC :: k -> k type family in two:

  • an open type family: AsRPC :: Type -> Type
  • a closed type family: TAsRPC :: T -> T

Incidentally, ended up discovering these AsRPC instances were not lawful:

  • OpenChestT
  • View_
  • Void_
  • ShouldHaveEntrypoints

Related issue(s)

Resolves part of #737 (closed)

Checklist for your Merge Request

Related changes (conditional)

  • Tests (see short guidelines)

    • If I added new functionality, I added tests covering it.
    • If I fixed a bug, I added a regression test to prevent the bug from silently reappearing again.
  • Documentation

    • I checked whether I should update the docs and did so if necessary:
    • I updated changelog files of all affected packages released to Hackage if my changes are externally visible.

Stylistic guide (mandatory)

Edited by Diogo Castro

Merge request reports