2012-05-17 19 views
13
data Ray = Ray Vector Vector 

oHaskell: datos algebraicos vs Tupla

type Ray = (Vector, Vector) 

que es el preferido en Haskell idiomática? ¿Por qué debería usar uno sobre el otro?
No me importa el rendimiento.

parece que tiene poca diferencia con las funciones, por ejemplo:

trace :: Ray -> … 

trace (Ray x d) = … 
-- OR 
trace (x, d) = … 

Respuesta

10

Se prefiere la versión data ya que indica más claramente la intención del programador - mediante la creación de un nuevo tipo, que están señalando a todos que esto no es simplemente una tupla, sino una entidad semántica significativa, un Ray.

Eso permite seguir adelante con el sistema de tipo, con instancias personalizadas para Ray y optimizaciones no posibles en tuplas.

+1

Derecha. Y un punto crítico sobre los tipos: son mucho más que la representación de datos; ellos caracterizan la estructura útil. – pigworker

+0

Está bien, eso tiene sentido. 'type' es realmente solo para un sinónimo, no un nuevo tipo de datos. Pero la línea tiene que dibujarse en alguna parte, 'tipo Color = (Int, Int, Int)' sería apropiado, ¿no? – mk12

+2

No, por razones de rendimiento, tiene más sentido tener un tipo de vector empaquetado para Color, como en el paquete de color: tipos significativos como este pueden optimizarse y especializarse. http://hackage.haskell.org/packages/archive/colour/2.3.3/doc/html/src/Data-Colour-Internal.html#Colour –

6

También puede considerar una tercera opción que es una especie de combinación de los dos: newtype

newtype Ray = Ray (Vector, Vector) 

tipos de datos algebraicos, en mi opinión, se utiliza en situaciones en las que tiene varias alternativas, o en los casos en necesitas que el tipo sea recursivo, conteniéndose a sí mismo. Pero podría ser demasiado para algo como esto.

Don Stewart señaló que hacer un sinónimo de tipo para tupla es lo mismo que usar ese tipo de tupla directamente; Los sinónimos tipo no tienen identidad propia. Por lo tanto, el verificador de tipos no podrá distinguir entre su tipo y una tupla, por lo que no puede verificar si está utilizando el tipo que desea. Además, tendría las mismas instancias exactas que una tupla.

A newtype le permite usar el mismo tipo subyacente que la tupla; pero es un tipo diferente al verificador de tipos, con instancias separadas.

+0

Esto parece ser menos común que usar la forma al curry. Tal vez solo porque es más puntuación. – luqui

3

Una cuarta alternativa que encontré muy conveniente registros son:

data Ray = Ray { from, to :: Vector } 

Ellos tienen básicamente todas las características de los ADT "normales", pero con un poco de azúcar sintáctica adicional. Especialmente hacen que sea más fácil obtener copias parcialmente modificadas de un valor. Es cierto que los registros son demasiado limitados en algunas situaciones, pero luego puede ir más allá con "versiones mejoradas" como fclabels.