|
|
||
|
|
Start of topic | Skip to actions
Joseph gave a presentation on his efforts to write a lambda-calculus interpreter in coq and extract OCaml code from it. Advantages of using coq instead of concoqtion
ExtractionWe don't want to write the interpreter to run under coq for several reasons, including a strict termination requirement and lack of side effects. So we want the code to eventually run with OCaml using its facilities, which is done by "exracting" OCaml code from coq code by a coq library utility. This sacrifices some safety properties to get Turing-complee features. UsageTop level: Recursive Extraction f Extracion "file.ml" fwhere f is a coq function. (* define type *) Axiom P:Set. Recursive Extraction P. Extraction as conversionWe didn't get too deep into this.c ::= Set | Prop | \Pi x: e. c | \lambda x. c. c | ... | c c \Gamma |- c_1 : c_2 \Gamma |- \Pi x:c .c c_3 t ::= p [primitive] | t t | \lambda x.t | . | ... if S = Prop then . else [\Gamma |- c_1] -> [\Gamma |- c_2] a) Set -> type; RemarksConcoqtion separates OCaml types from Coq types, making the former dynamic and the latter static. Coq functions bridge the gap, allowing for some manipulations of kinds that are consistent with the runtime code (e.g. in interpreter we implemented before: evalE & evalT). Correspondence of concoqtion type vs coq types is listed in Joseph's post on the wiki. In evaluation, we have context refinement in concoqtion but not in coq. So we need to work around by using tactics. Walid: staging is very difficult to do automatically; in concoqtion, separation b/w types and terms guarantees that the analysis doesn't break. Instead we need to supply a lot of details by hand. Black magic used by extractorSince coq's type system is more flexible than OCaml's, sometimes the extracted code won't typecheck nicely in OCaml. Here are some type system-cheating functions provided by OCaml that the extractor uses to get around this issue. Maybe if the target language were Haskell, a lot of these black magic might be unnecessary. The target language for the extractor ought to be F_\omega, but no language implements it as such. Obj.tObj.t is "any" type or untyped, type. Any type is substitutable with Obj.t, and vice versa. No runtime type checking is performed. The extractor uses this liberally to beat OCaml's type sys. This is "unsafe" in sense that it kills type safety, but if we assume that the extractor is well written, it is not a problem unless we edit the code. Obj.magicWe've seen this before. It casts any type to any type. Type (kind) of typed termHere's the initial try. tterm : Env -> Typ -> Set It closely mirrors the kind for the concoqtion version.
type ('e:'(Env), 't:'(Typ)) tterm
Now we want to eliminate evalE, evalT to make a difference: tterm : Set -> Set -> Type But then extraction breaks (doesn't compile). The problem is that OCaml doesn't support polymorphic recursion; first branch of the match in the evaluator dictates what return type can be, but since we're using untagged values, each branch returns different things. We have two fixes. 1) add Obj.magic everywhere in extracted code; 2) hack (emulate) polymorphic recursion. The latter works by using universal quantifiers allowed inside record types. Then we can perform polymorphic recursion by manually modifying the code. Polymorphic recursion in (pure) OCamlA recursive function that feeds itself different types of objects, or returns different type objects, depending on its input cannot be typed in Hindley-Milner.
let rec eval (exp: ('a, 'b) tterm) (e:env) : 'a =
match exp with
| [something that guarantees 'a = int] -> 0
| [something that guarantees 'a = string] -> ""
;;
We can get around this by passing around the function to be recursively called as a parameter. We can't just pass the function itself, however, so we need to wrap it in a record type to hide the forall.
type q = { reccall : 'a 'b. q -> ('a, 'b) tterm -> 'a -> 'b }
reccall is bound to the recursive function itself, allowing for passing around of polymorphic function. A DiscoveryJoseph found that writing a wrapper function that takes only the term and calls the real evaluator with env=unit, guaranteeing that initial env is unit, fixes problem, i.e. the extracted code type checks. It seems that the presence of the wrapper function makes the extractor add extra Obj.magic.
Topic Actions: Edit | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r6 < r5 < r4 < r3 < r2 | More topic actions
Webs: Main | TWiki | Africa | EmbeddedSystems | Gpce | Houston | International | K12 | MetaOCaml | MulticoreOCR | ProgrammingLanguages | RAP | RIDL | Sandbox | SpeechClub | Teaching | Texbot | WG211 Web Actions: |
|
This work is licensed under a Creative Commons Attribution 2.5 License. Please follow our citation guidelines.