2010-06-28 6 views
23

tipos Embalaje, como Int# y funciones estrictas, como f (!x) = ..., son algo diferente, pero no veo similitud conceptual - no permitir que thunks/pereza de alguna manera. Si Haskell era un lenguaje estricto como Ocaml, cada función sería estricta y cada tipo no incluido. ¿Cuál es la relación entre los tipos sin caja y la exigencia de rigor?¿Cuál es la relación entre los tipos sin caja y el rigor?

+1

No tengo mucha experiencia con tipos no compartidos, por lo que incluso comentarios básicos son bienvenidos. – sdcvvc

+3

No todos los tipos se desempaquetarán debido a polimorfismo. Las funciones polimórficas en OCaml y Haskell usan una representación uniforme de valores como cierres. Haskell permite la especialización, la generación de funciones personalizadas que utilizan argumentos unboxed (OCaml probablemente también lo haga). –

Respuesta

32

Sin Embalaje vs caja de Datos

Para apoyar parametric polymorphism y laziness, por defecto los tipos de datos de Haskell están representados de manera uniforme como un puntero a una closure en the heap, con una estructura como esta:

alt text

Estos son valores "encasillados". Un unboxed objeto está representada por el valor en sí directamente, sin ningún tipo de indirección o cierre. Int está en caja, pero Int# está desagrupado.

Lazy values ​​requieren una representación en caja. Los valores estrictos no: pueden representarse como cierres totalmente evaluados en el montón, o como estructuras primitivas unboxed. Tenga en cuenta que pointer tagging es una optimización que podemos usar en objetos encuadrados, para codificar el constructor en el puntero al cierre.

la relación con rigurosidad

Normalmente, los valores unboxed se generan de manera ad hoc por los compiladores de lenguaje funcional. En Haskell, sin embargo, unboxed values son especiales.Ellos:

  1. tienen un tipo diferente, #;
  2. solo se puede usar en lugares especiales; y
  3. están sin elevar, por lo que no se representan como un puntero a un valor de almacenamiento dinámico.

Debido a que no están elevados, son necesariamente estrictos. La representación de la pereza no es posible.

Así que los tipos de unboxed particulares, como Int#, Double#, realmente se representan como dobles o int en la máquina (en notación C).

Análisis Rigor

Por otra parte, GHC hace strictness analysis de tipos de Haskell regulares. Si el uso de un valor es estricto, es decir, nunca puede estar "indefinido", el optimizador puede reemplazar todos los usos del tipo normal (por ejemplo, Int) con un contenedor (Int#), ya que sabe que el uso de Int es siempre estricto, y por lo tanto el reemplazo con el tipo más eficiente (y siempre estricto) Int# es seguro.

Por supuesto, podemos tener estrictas tipos sin unboxed tipos, por ejemplo, un elemento-lista estricta polimórfica:

data List a = Empty | Cons !a (List a) 

es estricta en sus elementos, pero no los representa como valores sin embalaje.

Esto también señala el error que cometió con respecto a los idiomas estrictos, like OCaml. Todavía necesitan compatibilidad con el polimorfismo, por lo que proporcionan una representación uniforme o se especializan en tipos de datos y funciones para todos los tipos. GHC usa de forma predeterminada una representación uniforme, al igual que OCaml, aunque GHC también puede usar specialize types and functions ahora (como plantillas C++).

+0

Entonces, ¿hay algún uso de un tipo de caja estricta, como su ejemplo 'List'? ¿No tiene la misma representación que su contraparte perezosa? – haskelline

+0

Tiene la misma representación, pero semántica diferente. Tales estructuras son a menudo útiles. –

+1

Pero pensé, por ejemplo, 'data Pair = P Int Int' contendrá más indirecciones que' data Pair = P! Int! Int'. En el primero, ¿cada argumento es un puntero a un puntero (un thunk), y en este último es un puntero a un valor? – haskelline

17

tipos Unboxed son necesariamente estricta, pero no todos los valores estrictos son necesariamente sin embalaje.

data Foo a = Foo !a !a 

tiene dos campos estrictas

data Bar a = Bar {-# UNPACK #-} !Int !a 

tiene dos campos estrictas, pero el primero es sin embalaje.

En última instancia, los tipos razón sin embalaje son (necesariamente) estricta es que no hay lugar para almacenar el golpe seco, ya que son tontas, datos simple y llanamente en ese punto.

7

Argumentos de cualquier tipo se pueden hacer "estricta", pero los únicos tipos unboxed que han tipos en cajas correspondientes son Char#, Int#, Word#, Double# y Float#.

Si conoces a lenguajes de bajo nivel como C, es más fácil de explicar. Los tipos no compartidos son como int, double, etc., y los tipos encuadrados son como int*, double*, etc. Cuando tiene un int, ya conoce el valor completo tal como está representado en el patrón de bits, por lo tanto, no es perezoso. También debe ser estricto, ya que todos los valores de int son válidos y no ⊥.

Sin embargo, dada una int* puede optar por eliminar la referencia al puntero tarde para obtener el valor real (por lo tanto perezoso), y es posible tener punteros no válidos (que contiene ⊥, es decir, no estricto).

Cuestiones relacionadas