2010-07-19 7 views
14

Viniendo a Haskell desde un fondo en varios lenguajes de OO, una cosa que me parece un inconveniente es que la función y los nombres de campo no tienen el alcance de los tipos que están asociados, por lo que es fácil encontrarse con enfrentamientos si los diferentes tipos de datos tienen campos con el mismo nombre.Choques de nombres entre etiquetas de campo de diferentes tipos de datos en Haskell

Si tengo estos tres módulos:

module One where 

data Foo a = Foo { value :: a } 

---- 

module Two where 

data Bar a = Bar { value :: a } 

---- 

module Three where 

import One 
import Two 

foo = Foo { value = 42 } -- compile error here 
n = value foo -- and here 

las referencias no calificadas a value en el módulo Three se consideran ambigua pesar de que sólo uno de los dos nombres importados tiene sentido en este contexto. (En un lenguaje orientado a objetos, las referencias a foo.value y bar.value serían sin ambigüedades.)

Por supuesto que puedo eliminar la ambigüedad escribiendo Foo { One.value = 42 }, pero que no augura nada bueno. También puedo nombrar los campos de manera diferente, p. "fooValue" y "barValue", pero la redundancia en Foo { fooValue = 42 } parece incómoda también.

Este es realmente un caso especial de la cuestión más general de funciones en diferentes módulos que tienen el mismo nombre pero operan en diferentes tipos no relacionados. Sin embargo, parezco encontrarlo más a menudo con los nombres de los campos. Por ejemplo, tengo varios tipos de datos, no relacionados por una clase de tipo pero que a menudo se usan juntos, que contienen valores de color, por lo que me gustaría que cada uno tenga un campo llamado "color".

¿Cómo nombran los desarrolladores experimentados de Haskell cosas y los organizan en módulos para evitar este tipo de situaciones?

+0

Punto menor: le falta el constructor en su definición de 'Bar'. –

+0

@Travis Brown: Vaya, eso fue un error tipográfico. Gracias por mencionarlo. – Wyzard

Respuesta

9

La extensión GHC -XDisambiguateRecordFields permitirá foo = Foo { value = 42 } (pero no n = value foo).

Hay un large body of literature sobre las deficiencias del sistema de registro actual de Haskell y los candidatos para su reemplazo, así como un puñado de bibliotecas que intentan proporcionar mejores soluciones ahora. fclabels es el único que he usado personalmente.

This StackOverflow question es similar, y algunas de las respuestas también pueden serle útiles.

Esto es realmente un caso especial de la cuestión más general de las funciones en módulos diferentes que tienen el mismo nombre pero operan en diferentes tipos, no relacionados.

Qualified imports y alias suelen ser suficientes para resolver este problema.

1

Puede considerar una clase de tipo, si hay una función de acceso común en todos estos tipos. P.ej.

class Fieldable a where 
    field :: a -> b 

instance Fieldable (a,b) where 
    field = fst 

Etc.

+1

¿Pueden los nombres de campo de un tipo de datos ser parte de una instancia de clase? Si hago una 'clase Valued ab donde value :: a -> b', para asociar mis dos tipos con ella, tendría que hacer algo como' instancia Valued (Foo a) a donde value = value' y eso no es así válido (los dos significados del conflicto de 'valor'). Parece que no puedo definir una función como parte de una instancia de clase si su nombre ya está definido de antemano. – Wyzard

2

¿Cómo experimentados desarrolladores Haskell nombre a las cosas, y organizarlas en módulos, para evitar este tipo de situaciones?

sólo he trabajado con algunos desarrolladores con experiencia en Haskell, y hacen cosas muy parecido

data Foo a = Foo { foo_value :: a } 

data Bar a = Bar { bar_value :: a } 

o incluso

data Apocalypse a = A { ap_value :: a } 

En general, tengo la sensación de que muchos A los antiguos Haskellers no les gustan los nombres calificados y realmente quieren fingir que el mundo tiene solo un gran espacio de nombres, directamente de las edades oscuras. (Hubo un tiempo en que los compiladores de C tenían las mismas restricciones en los nombres de campo, por lo que el modo en un struct stat se llama st_mode y no simplemente mode.)

Usted puede sobrecargar nombres con clases de tipos, pero los desarrolladores con experiencia Sé que no me gustan las clases de tipos gratuitas. Nunca me puedo imaginar cuándo piensan que una clase de tipo será gratuita o no.

Espero que algún día la gente de Haskell llegue a un acuerdo con un espacio de nombre jerárquico y comenzará a usar nombres calificados. Como Dios quiso.

+0

Cuando en realidad no quiere selectores de registros polimórficos, tiene sentido para mí no forzarlos solo por alguna conveniencia sintáctica menor. Incluso si puede usar cosas calificadas, me parece que reclamar un nombre común para un campo poco utilizado, especialmente uno que normalmente solo se puede acceder a través de una función auxiliar, es una mala forma. – sclv

+0

He estado usando nombres calificados tanto como puedo. El lenguaje mismo lo trata bien; el único problema es que Haddock se vuelve mucho menos útil con nombres calificados porque todavía asume el espacio de nombres grande. (Puede hacer que los nombres de tipo de espectáculo de Haddock sean calificados, pero aún mostrará hipervínculos no calificados). –

Cuestiones relacionadas