ventajas reasonml online languages desventajas caracteristicas ocaml

ocaml - online - reasonml



En OCaml, qué definición de tipo es esta: ''a. unidad-> ''a (1)

''a. significa "para todos los tipos ''a". El nivel superior de OCaml normalmente no se molesta en mostrarlo, por lo que no aparece en la salida. Cualquier expresión impresa que contenga variables de tipo tiene un inicio implícito para todos al inicio, a menos que se muestre en otro lugar.

Al definir una función, puede ser útil agregar esto al principio para asegurar que el tipo sea polimórfico. p.ej

# let f : (''a -> ''a) = fun x -> x + 1;; val f : int -> int = <fun>

Aquí, ''a -> ''a solo restringe el tipo de salida de la función para que sea el mismo que su tipo de entrada, pero OCaml es libre de limitarlo aún más. Con la ''a. , esto no sucede

# let f : ''a. (''a -> ''a) = fun x -> x + 1;; Error: This definition has type int -> int which is less general than ''a. ''a -> ''a

Necesitas especificar el ''a. al definir tipos de registro u objeto y desea extender la variable de tipo a un miembro individual en lugar de a todo el objeto.

Preguntas

Fue mi primera vez que vi una definición de tipo como ''a. unit -> ''a ''a. unit -> ''a en tipo polimórfico explícito en registro

Q1 : ¿Qué es esto ''a. (note el punto)?

P2 : ¿Cuál es la terminología para este tipo de definición de tipo?

Si lo hago

let f:''a. ''a list -> int = fun l -> List.length l;;

programas de utop

val f : ''a list -> int = <fun>

P3 : ¿Por qué utop no muestra el tipo ''a. ''a list -> int ''a. ''a list -> int ?

P4 : ¿Cuándo debo usar este tipo de definición de tipo?

Además, puedo usar este tipo de definición en el registro:

type t = { f: ''a. ''a list -> int};; (* this is correct *)

pero no puedo usarlo en variantes:

type t = Node of (''a. ''a list -> int);; (* this is wrong *)

Q5 : ¿por qué?

Actualización / Resumen

Hice algunos experimentos con esta forall type definition ya que no puedo encontrar ningún artículo en la web sobre este tema en OCaml y quiero inductarme para averiguar qué hay detrás.

Resumo estos experimentos aquí y espero que alguien pueda dar más información.

De la answer continuación y sus comentarios, me siento ''a. Es una especie de force forall .

1. ''a. en definición de función

let f:(''a -> int) = fun x -> x + 1 (* correct *)

Lo anterior está bien porque OCaml es libre de reducir el tipo de parámetro de f y reemplazar ''a con int .

Sin embargo,

let f:''a. (''a -> int) = fun x -> x + 1 (* wrong *)

Esto no pasará el compilador, ya que obliga a que f sea ​​aplicable en all types través de ''a. . Aparentemente, desde la parte de definición es imposible, ya que el único tipo posible para x es int .

Este ejemplo es interesante ya que muestra la lógica y la magia detrás del sistema de inferencia de tipo estático de OCaml. Los tipos normalmente se muestran naturalmente a partir de la definición de la función, es decir, te importa más lo que hace la función, en lugar de dar un tipo primero.

Para mí, tiene poco sentido usar ''a. al definir funciones, como si la definición de la función puede manejar todos los tipos, su tipo será naturalmente ''a. ; Si la función no puede manejar todos los tipos, no tiene sentido forzar todos los tipos. Supongo que esta es una de las razones por las que el nivel superior de OCaml generalmente no se molesta en mostrarlo

2, ''a. en tipo inferir

let foo f = f [1;2;3] + f [4;5;6] (* correct *)

la función f se deducirá como int list -> int porque OCaml ve [1;2;3] primero y es una int list , por lo que OCaml asume que f tomará la int list .

También es por esto que el siguiente código falla ya que la segunda lista es la string list

let foo f = f [1;2;3] + f ["1";"2";"3"] (* wrong*)

Incluso si sé que List.length sería un buen candidato para f , OCaml no lo permitirá debido al tipo de sistema inferir.

Pensé que si fuerzo a ser ''a. , entonces f puede manejar tanto la int list string list en foo , así que hice:

let foo (f:''a. ''a list -> int) = f [1;2;3] + f ["1";"2";"3"];; (* wrong *)

Falló y parece que OCaml no lo permite. y supongo que esta es la razón por la que no siempre se puede hacer inferencia de tipo en presencia de polimorfismo imprevisivo, por lo que OCaml restringe su uso para registrar campos y métodos de objetos.

3. ''a. en registro

Normalmente tomo ''a del parámetro de tipo como este:

type ''a a_record = {f: ''a list -> int};; (* correct *)

Sin embargo, la limitación es que una vez que apliques obtienes el tipo concreto:

let foo t = t.f [1;2;3] + t.f [4;5;6];; (* correct *)

OCaml int a_record t como un int a_record , no más un ''a a_record . Así que lo siguiente fallará:

let foo t = t.f [1;2;3] + t.f ["1";"2";"3"];; (* wrong*)

En este caso, podemos utilizar ''a. como OCaml lo permite en el tipo de registro.

type b_record = {f: ''a. ''a list -> int};; (* correct *) let foo t = t.f [1;2;3] + t.f ["1";"2";"3"];; (* correct *)

b_record es en sí mismo un tipo de registro concreto y su f se puede aplicar a todos los tipos de listas. entonces nuestro foo arriba pasará OCaml.