Skip to content
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

Mutually recursive modules #38

Open
gfngfn opened this issue Sep 1, 2021 · 2 comments
Open

Mutually recursive modules #38

gfngfn opened this issue Sep 1, 2021 · 2 comments

Comments

@gfngfn
Copy link
Owner

gfngfn commented Sep 1, 2021

Since it is often required in Erlang that two kinds of processes have the ability to actively start to send data to each other, it is desirable that modules can be mutually dependent.

In order to formalize a type system for recursive modules, it is not sufficient to introduce the mechanism of the forward declaration of signatures that will be assigned to recursive modules, because of the so-called double vision problem [Dreyer 2007]. Since the RMC type system [Dreyer 2007], MixML [Rossberg & Dreyer 2013], etc. remedy the problem, we can possibly utilize them as a basis of the type system for Sesterl.

However, it is never trivial how to extend RMC or MixML for handling the static interpretation [Elsman, Henriksen, Annenkov & Oancea 2018], which is a method for statically generating modules from functor applications; the mechanism of the static interpretation is crucial for Sesterl so that the resulting programs can be represented by Erlang modules.

(More explanation should be added here)

import rec BarServer

module FooServer :> sig
  type proc
  val notify<$a> : proc -> [$a]unit
  ...
end = struct
  module Callback = struct
    ...
    val handle_info(...) = act
      ... BarServer.notify(...) ...
        /* sends data to a process that is working based on the `BarServer` module */
    ...
  end

  module Impl = GenServer.Make(Callback)

  type proc = Impl.proc

  val notify(p) = act
    Impl.cast(p, ...)
  ...
end
import rec FooServer

module BarServer :> sig
  type proc
  val notify<$a> : proc -> [$a]unit
  ...
end = struct
  module Callback = struct
    ...
    val handle_info(...) = act
      ... FooServer.notify(...) ...
        /* sends data to a process that is working based on the `FooServer` module */
    ...
  end

  module Impl = GenServer.Make(Callback)

  type proc = Impl.proc

  val notify(p) = act
    Impl.cast(p, ...)
  ...
end

A minimal example case of double vision problem:

/* A.sest */
import rec B

module A :> sig
  type u = B.u
  type t :: o
  val f : fun(t) -> {u, t}
end = struct

  type u = B.u

  type t = int

  val f(x : t) : {u, t} =
    let {y, z} = B.g (x + 3) in
      /* Assume that the type system does not handle the double vision problem:
         The type environment here tracks the fact `B.g : fun(A.t) -> {B.u, A.t}`
         but cannot recognize that `A.t` equals `int`.
         Therefore, a type error will occur here. */
    {y, z + 5}

end
/* B.sest */
import rec A

module B :> sig
  type t = A.t
  type u :: o
  val g : fun(t) -> {u, t}
end = struct

  type t = A.t

  type u = bool

  val f(x : t) : {u, t} =
    ...

end

Bibliography

@michallepicki
Copy link
Contributor

michallepicki commented Sep 18, 2021

Is this only a code organization limitation? Meaning, can't this run-time behavior be curently achieved when carefully splitting the message types (contract) and two GenServer implementations in additional modules?

edit: I've been staring at the example and indeed I don't have an immediate idea of how it could be split, so it could be an expresiveness limitation.

@michallepicki
Copy link
Contributor

michallepicki commented Sep 25, 2021

This may or may not be of use to you (I stumbled upon it when looking for something else): Pauli Jaakkola A type system for first-class recursive ML modules and https://github.com/nilern/r1ml

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

No branches or pull requests

2 participants