Tipos en Lisp y Esquema

8

Ahora veo que Racket tiene tipos. A primera vista, parece ser casi idéntico a la escritura de Haskell. Pero, ¿el CLOS de Lisp cubre algunos de los tipos de espacio que cubre Haskell? Crear un tipo de Haskell muy estricto y un objeto en cualquier lenguaje OO parece vagamente similar. Es solo que he bebido un poco de Kool-Aid de Haskell y estoy totalmente paranoico por el hecho de que si voy por la carretera de Lisp, estaré atornillado debido a la escritura dinámica.

    
pregunta user2054900 17.02.2013 - 01:56

2 respuestas

3

El sistema de tipo CL es más expresivo que el de Haskell, por ejemplo, puede tener un tipo (or (integer 1 10) (integer 20 30)) para un valor 1,2,...9,10,20,21,...,30 .

Sin embargo, los compiladores Lisp no obligan a que comprendan la seguridad de tipos en su garganta, por lo que puede ignorar sus "notas": bajo su propio riesgo .

Esto significa que puedes escribir Haskell en Lisp (por así decirlo) declarando todos los tipos de valores y asegurándote cuidadosamente de que se inferan todos los tipos necesarios, pero en primer lugar es más fácil usar Haskell.

Básicamente, si quieres una escritura estática fuerte, usa Haskell o OCaml, si quieres una escritura dinámica fuerte, usa Lisp. Si quieres una escritura estática débil, usa C, si quieres una escritura dinámica débil, usa Perl / Python. Cada camino tiene sus ventajas (y fanáticos) y desventajas (y detractores), por lo que se beneficiará de aprenderlos todos.

    
respondido por el sds 17.02.2013 - 04:59
3

Typed Racket es muy diferente de Haskell. Los sistemas de tipos en Lisp y Scheme, y de hecho los sistemas de tipos en ecosistemas de lenguaje tradicionalmente no tipificados en general, tienen el objetivo fundamental de que otros sistemas de tipo no sean interoperando con el código no tipificado existente . Typed Racket, por ejemplo, introdujo reglas de escritura completamente nuevas para adaptarse a varios idiomas de Racket. Considera esta función:

(define (first some-list)
  (if (empty? some-list)
      #f
      (car some-list)))

Para listas no vacías, esto devuelve el primer elemento. Para listas vacías, esto devuelve falso. Esto es común en las lenguas no tipificadas; un lenguaje escrito usaría algún tipo de envoltorio como Maybe o arrojaría un error en el caso vacío. Si quisiéramos agregar un tipo a esta función, ¿qué tipo debería usarse? No es [a] -> a (en notación de Haskell), porque puede devolver falso. Tampoco es [a] -> Either a Boolean , porque (1) siempre devuelve false en el caso vacío, no es un booleano arbitrario y (2) un tipo Either envolvería los elementos en Left y false en Right y requerirá que "desenvuelva el o bien "para llegar al elemento real. En cambio, el valor devuelve una unión verdadera : no hay constructores de ajuste, simplemente devuelve un tipo en algunos casos y otro tipo en otros casos. En Typed Racket, esto se representa con el constructor de tipo de unión:

(: first (All (A) (-> (Listof A) (U A #f))))
(define (first some-list)
  (if (empty? some-list)
      #f
      (car some-list)))

El tipo (U A #f) indica que la función podría devolver un elemento de la lista o falso sin ninguna instancia de ajuste de Either . El verificador de tipos puede inferir que some-list es de tipo (Pair A (Listof A)) o la lista vacía, y además infiere que en las dos ramas de la declaración if se sabe cuál de ellas es el caso . El comprobador de tipos sabe que en la expresión (car some-list) , la lista debe tener el tipo (Pair A (Listof A)) porque la condición if lo garantiza. Esto se denomina aparición de errores y está diseñado para facilitar la transición del código no tipificado al código escrito.

El problema es la migración. Hay una tonelada de código de Raqueta sin tipo por ahí, y la Raqueta con tipo no puede obligarte a abandonar todas tus bibliotecas sin tipo favoritas y pasar un mes agregando tipos a tu código base si quieres usarlo. Este problema se aplica cada vez que agrega tipos gradualmente a una base de código existente, consulte TypeScript y su Cualquier tipo para una aplicación javascript de estas ideas.

Un sistema de tipo gradual debe proporcionar herramientas para lidiar con expresiones comunes sin tipo e interactuar con el código existente sin tipo. Usarlo será bastante doloroso de lo contrario, consulte "¿Por qué ya no usamos Core? escribe " para un ejemplo de Clojure.

    
respondido por el Jack 26.05.2016 - 21:32

Lea otras preguntas en las etiquetas