12

OCaml's Hindley-Milner type system does not allow for impredicative polymorphism (à la System-F), except through a somewhat recent extension for record types. The same applies to F#.

It however is sometimes desirable to translate programs written with impredicative polymorphism (e.g. Coq) into such languages. The solution for Coq's extractor to OCaml is to (sparingly) use Obj.magic, which is a kind of universal unsafe cast. This works because

  • in OCaml's runtime system, all values have the same size regardless of their type (32 or 64 bits depending on architecture)
  • the more sophisticated type system applied to the original program guarantees type safety.

Is it possible to do something similar in F#?

David Monniaux
  • 1,564
  • 10
  • 21
  • 2
    Polymorphic record fields are not "recent" by most standards, as they were introduced in 2002 for 3.05. – gasche Mar 28 '13 at 22:57
  • 1
    It is worth mentioning that the meaning of "impredicative polymorphism" is different in the context of Coq. Coq does allow a type variable to be instantiated with a polymorphic type, but usually there are restrictions on when one can do so, even when the value is boxed. This is done to guarantee logical consistency. On the OCaml and Haskell side, what is being called "impredicative" is just being able to substitute an *unboxed* (i.e., not record) polymorphic type for a type variable. Thus, it is just a way to make higher-rank types more convenient. – Arthur Azevedo De Amorim Mar 30 '13 at 14:10

1 Answers1

10

It would be helpful if you could elaborate on exactly what you'd like to achieve. Some impredicative uses (such as this example from the Haskell wiki) are relatively easy to encode using an additional nominal type with a single generic method:

type IForallList =
    abstract Apply : 'a list -> 'a list

let f = function
| Some(g : IForallList) -> Some(g.Apply [3], g.Apply ("hello" |> Seq.toList))
| None -> None

let rev = { new IForallList with member __.Apply(l) = List.rev l }

let result = f (Some rev)
Community
  • 1
  • 1
kvb
  • 53,475
  • 2
  • 80
  • 126
  • 2
    Here's another example I wrote a few months ago: https://gist.github.com/mausch/3895976 – Mauricio Scheffer Mar 28 '13 at 20:28
  • The exact same thing can be done in OCaml with a record written as `type forall_list = {apply : 'a. 'a list -> 'a list}` and `let rev = {apply = List.rev}`. – didierc Mar 28 '13 at 22:04
  • 1
    Yes, this is the somewhat recent extension for record types that I alluded to (record fields may have universal types). – David Monniaux Mar 28 '13 at 22:21