son solo snp representan qué que polimorfismo para origen nucleotido mutaciones medica los información genética expresión enzimas definicion bioquimica biologico types programming-languages functional-programming ocaml ml

types - solo - ¿Variantes o variantes polimórficas?



que es polimorfismo en bioquimica (3)

La única razón por la que uso variantes polimórficas en la mayoría de las interfaces de módulos es para solucionar los problemas de nomenclatura de las variantes clásicas.

Si lo siguiente pudiera funcionar, las variantes polimórficas ya no serían útiles en la mayoría de los casos:

type t1 = String of string | Int of int | Bool of bool | List of t1 list type t2 = String of string | Int of int | Other let simplify x = match (x : t1) with String s -> String s | Int n -> Int n | Bool _ | List _ -> Other

2014-02-21 Actualización: el código anterior ahora es válido en OCaml 4.01. ¡Viva!

Noté que, entre los programadores de OCaml que conozco, algunos de ellos siempre usan variantes polimórficas (variantes que no están declaradas, prefijadas con una cita atrás), mientras que otros nunca usan variantes polimórficas, y prefieren variantes declaradas en tipos.

Excepto por razones de rendimiento (actualmente, las variantes polimórficas se compilan de manera menos eficiente que las variantes simples), ¿cómo los desarrolladores expertos de OCaml eligen entre ellas?


Mi uso se puede dividir en las siguientes 5 categorías. 1. interfaz 2. modularidad 3. legibilidad 4. brevedad 5. trucos

  1. Si el tipo de variante es solo interno al módulo, uso variantes regulares porque, como dijiste, se compilan más eficientemente.
  2. Si el tipo de variante se exporta en la interfaz y creo que algunos casos podrían aparecer en otros módulos, pero no necesariamente tendría sentido hacerlos dependientes del módulo, uso variantes polimórficas porque no están vinculadas al sistema de espacio de nombres de módulos. . Ejemplos: el tipo de tipo de codificación de Xmlm . Además, tener el tipo de señal como tipo de variante significa que puede desarrollar módulos utilizando la misma idea para el procesamiento de XML sin introducir una dependencia en Xmlm .
  3. Si el tipo de variante se exporta en la interfaz, a veces lo encuentro demasiado detallado para usar variantes regulares cuando se asignan valores del tipo de variante a las funciones del módulo. Ejemplo: el tipo de versión de Uuidm . En lugar de tener que escribir Uuidm.create Uuidm.V4 , simplemente puede escribir Uuidm.create `V4 , que es tan claro y menos detallado.
  4. A veces una función particular puede devolver diferentes casos. Si estos casos solo son utilizados por esta función, declaro el tipo de función en la interfaz sin tener que introducir una definición de tipo. Por ejemplo, parse : string -> [`Error of string | `Ok of t] parse : string -> [`Error of string | `Ok of t]
  5. Las variantes polimórficas y su subtipificación le permiten imponer invariantes estáticamente con tipos fantasma. Además, la posibilidad de definirlos incrementalmente puede ser útil, tanto para aplicar invariantes estáticamente como para fines de documentación.

Finalmente, a veces uso variantes polimórficas en la implementación de un módulo de acuerdo con 4. pero sin que aparezcan en la interfaz. Desanimo este uso a menos que declares las variantes polimórficas y las cierres porque debilita la disciplina de tipeo estático.


No es cierto que las variantes polimórficas sean siempre menos eficientes. Usando el ejemplo de Martin:

type base = [`String of string | `Int of int] type t1 = [base | `Bool of bool | `List of t1 list] type t2 = [base | `Other] let simplify (x:t1):t2 = match x with | #base as b -> b | `Bool _ | `List _ -> `Other

Para hacer esto con variantes estándar se requieren dos tipos distintos y una recodificación completa, con variantes polimórficas, el caso base es físicamente invariante. Esta característica realmente se destaca cuando se usa la recursión abierta para la reescritura de términos:

type leaf = [`String of string | `Int of int] type ''b base = [leaf | `List of ''b list] type t1 = [t1 base | `Bool of bool ] type t2 = [t2 base | `Other] let rec simplify (x:t1):t2 = match x with | #leaf as x -> x | `List t -> `List (List.map simplify t) | `Bool _ -> `Other

y las ventajas son aún mayores cuando las funciones de reescritura también se factorizan con recursión abierta.

Desafortunadamente, la inferencia del tipo Hindley-Milner de Ocaml no es lo suficientemente fuerte como para hacer este tipo de cosas sin una tipificación explícita, lo que requiere una cuidadosa factorización de los tipos, lo que a su vez dificulta la tipificación. Además, a veces se requieren coerciones explícitas.

El gran inconveniente de esta técnica es que, para los términos con múltiples parámetros, uno pronto termina con una explosión combinatoria de tipos bastante confusa, y al final es más fácil renunciar a la aplicación de la estática y usar un tipo de fregadero de cocina con comodines y excepciones. (es decir, tipado dinámico).