Coder Social home page Coder Social logo

mlsub's Introduction

This is a prototype type inferencer for an ML-like language with subtyping and polymorphism. It's written in OCaml, and building it requires Menhir.

It accepts lines containing programs written in a very limited subset of OCaml (just lambdas, unit and let), and spews some debugging output and their principal type if it likes them, and an unceremonious exception if it does not.

Some examples, and their inferred types:

The identity function is given type v0 -> v0. All free variables in inferred types are considered universally quantified, as is the custom in these parts.

fun x -> x
(v0 -> v0)

The inferencer actually spits out two types: the original and a simplified one. The second one is a simplified but equivalent rendering of the first. The simplifier is not currently very good.

Type ascriptions can be used, and check polymorphic subsumption:

(fun x -> x : a -> a)
(v0 -> v0)

The ascription may be less general than the inferred type:

(fun x -> x : unit -> unit)
(unit -> unit)

But the inferencer won't like a more general or unrelated type:

(fun x -> x : a -> b)
<error>

On to something more interesting. Self-application can be typed in this system:

fun x -> x x
(((v1 -> v0) & v1) -> v0)

The argument x must be both a v1 -> v0 and a v1. One thing you can do with the self-application function is apply it to itself (why you would do this is outside the scope of this work):

(fun x -> x x) (fun x -> x x)
Bot

This is the bottom type, equivalent to just a (universally quantified). We can check this with a type ascription:

((fun x -> x x) (fun x -> x x) : a)
Bot

The Y combinator can be typed by this system (here showing the simplified type, the first attempt is a bit uglier):

(fun f -> (fun x -> f (x x)) (fun x -> f (x x)))
((v0 -> v0) -> v0)

This version of the Y combinator doesn't work in strict languages. The CBV-safe version eta-expands, giving:

(fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)))
(((v1 -> v0) -> ((v1 -> v0) & v2)) -> v2)

This is slightly different from the expected ((a -> b) -> (a -> b)) -> (a -> b). An ascription check shows that it is more general:

(fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)) :
  ((a -> b) -> (a -> b)) -> (a -> b))
(((v1 -> v0) -> (v1 -> v0)) -> (v1 -> v0))

The extra generality comes from allowing v2 to be more general than v1 -> v0, which comes into play if -> has subtypes.

We can use fixpoint combinators to make values with recursive types, such as a function that takes arbitrarily many arguments:

(fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v))) 
   (fun f -> fun x -> f)
(Top -> rec v0 = (Top -> v0))

This type could be folded into the simpler rec a = Top -> a; but the (rather stupid) simplifier can't figure that out yet.

mlsub's People

Contributors

stedolan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mlsub's Issues

How do I build this on Ubuntu / Ubuntu WSL2 ?

How do I build this on Ubuntu / Ubuntu WSL2 ?

$ sudo apt install ocaml
$ sudo apt install opam
$ opam install ocamlfind
$ opam install menhirLib
$ make
ocamlbuild -no-hygiene -r -cflag -bin-annot -cflag -g -lflag -g -pkg menhirLib -pkg str -use-menhir -yaccflag --explain -yaccflag --table main.byte
ocamlfind: Package `menhirLib' not found
Cannot run Ocamlfind.
make: *** [Makefile:3: all] Error 2
$ opam install menhirLib
[NOTE] Package menhirLib is already installed (current version is 20200624).

"location.ml", line 47 - This expression has type bytes but an expression was expected of type string

$ make
ocamlbuild -no-hygiene -r -cflag -bin-annot -cflag -g -lflag -g -pkg menhirLib -pkg str -use-menhir -yaccflag --explain -yaccflag --table main.byte
+ ocamlc.opt -c -bin-annot -g -I /home/aaron/.opam/default/lib/menhirLib -I /usr/lib/ocaml -o location.cmo location.ml
File "location.ml", line 47, characters 15-38:
47 |   source fname (slurp (open_in fname))
                    ^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type bytes but an expression was expected of type
         string
Command exited with code 2.
Compilation unsuccessful after building 8 targets (7 cached) in 00:00:00.
make: *** [Makefile:3: all] Error 10

online demo gives different results from what the readme says

(fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)))
gives
((((a & a) -> (b | b)) -> ((a -> b) & c)) -> c) instead of (((v1 -> v0) -> ((v1 -> v0) & v2)) -> v2)

(fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v))) (fun f -> fun x -> f)
gives
((Top) -> ((Top) -> ((Top) -> (rec b = ((Top) -> (rec a = ((Top) -> (a | b)) | b)) | rec d = ((Top) -> (rec c = ((Top) -> (c | d)) | d))))))
instead of (Top -> rec v0 = (Top -> v0))

Sum types?

Are sum types supported? If so, would it be possible to document the syntax used in the demo?

Warning 8 [partial-match]: this pattern-matching is not exhaustive.

Getting the following :-

File "camlgen.ml", lines 31-61, characters 16-28:
31 | ................(loc, Some exp) = match exp with
32 |   | Var v -> CVar v
33 |   | Lambda (args, body) ->
34 |      assert false
35 |      (* CLambda ([args], lower g body) *)
...
58 |   | GetField (obj, field) ->
59 |      withtmp (lower g obj) (fun obj ->
60 |        CApp (CRaw "get_field", [obj; CInt (Symbol.hash field)]))
61 |   | _ -> CRaw "assert false"
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
(Loc (_, _, _), None)

license?

what's the license for the provided mlsub typechecker code? MIT?

type union position / subtyping lattice traversal

Is there a description on why mlsub chooses {x: T1|T2, y: T3|T4} over {x:T1,y:T3}|{x:T2,y:T4} when computing a type union of {x:T1,y:T3} and {x:T2,y:T4}?

I understand that both typings are technically correct but want to know whether it is possible to steer the computation so it would produce the second option (union of records instead of record of unions)

Edit: more general question is, how does one encode a different options of traversing the subtyping lattice when there's multiple paths between types?

What happened to 'fun'

What happened to 'fun' and how do I use this thing ?

It might be an idea to update the README.

Compilation unsuccessful

mborch@wavel:~/co/mlsub$ make all
ocamlbuild -no-hygiene -r -cflag -bin-annot -cflag -g -lflag -g -pkg menhirLib -pkg str -use-menhir -yaccflag --explain main.byte
+ /Users/mborch/.opam/4.02.3/bin/ocamlc.opt -c -bin-annot -g -I /Users/mborch/.opam/4.02.3/lib/menhirLib -I /Users/mborch/.opam/4.02.3/lib/ocaml -o camlgen.cmo camlgen.ml
File "camlgen.ml", line 31, characters 16-1095:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
(_, None)
+ /Users/mborch/.opam/4.02.3/bin/ocamlc.opt -c -bin-annot -g -I /Users/mborch/.opam/4.02.3/lib/menhirLib -I /Users/mborch/.opam/4.02.3/lib/ocaml -o source.cmo source.ml
File "source.ml", line 17, characters 11-30:
Error: Unbound module P.MenhirInterpreter
Command exited with code 2.
Compilation unsuccessful after building 28 targets (0 cached) in 00:00:00.
make: *** [all] Error 10

Building build-js also fails:

mborch@wavel:~/co/mlsub$ make build-js
ocamlbuild -r -build-dir _build.js -use-ocamlfind -pkg menhirLib -use-menhir \
	  -package js_of_ocaml -package js_of_ocaml.syntax \
          -syntax camlp4o webpage.byte
+ ocamlfind ocamlc -c -syntax camlp4o -package js_of_ocaml.syntax -package js_of_ocaml -package menhirLib -o webpage.cmo webpage.ml
File "webpage.ml", line 26, characters 16-30:
Error: Unbound value Parser.modlist
Command exited with code 2.
Compilation unsuccessful after building 25 targets (24 cached) in 00:00:00.
make: *** [build-js] Error 10

Type exponentially more complex than necessary

In the demo, I tried let rec x = {f1=x} and got x : ({f1 : rec a = ({f1 : a})}). This seems correct, but wouldn't x : rec a = {f1 : a} be simpler?

I also tried let rec x = {f1=x;f2=x;f3=x;f4=x;f5=x;f6=x;f7=x} and got a huge type expression, apparently exponential in the number of fields. I think this is just x : rec a = {f1 : a, f2 : a, f3 : a, f4 : a, f5 : a, f6 : a, f7 : a}?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.