2011-12-14 28 views
6

tengo algo de Haskell repetitivo que se ve algo como esto:Haskell dinámica de tipo de datos alteración

data Configuration 
    { confA :: Integer 
    , confB :: Boolean 
    , confC :: String } 

x = (\arg opt -> opt{ confA=arg }) 
y = (\arg opt -> opt{ confB=arg }) 
z = (\arg opt -> opt{ confC=arg }) 

y me gustaría que quitar la plancha de caldera, produciendo algo en la línea de:

setter :: (Config -> a) -> a -> Config -> Config 
x = setter confA 
y = setter confB 
z = setter confC 

Pero no tengo idea de cómo construir una función como setter. ¿Es esto posible incluso en haskell (no de plantilla) o estoy chocando contra el azúcar de sintaxis aquí? Si es así, ¿cómo haría algo así en la plantilla haskell?

Respuesta

13

Esto no es posible solo con el sistema de registro de Haskell. Lo que quiere son lentes ; este previous Stack Overflow question y su respuesta superior son una buena introducción. Personalmente, utilizo el paquete data-lens mencionado allí. (Ver también data-lens-fd para usarlo con la clase de MonadState MTL - si usted no sabe lo que es, sólo sé que es probable que se debe utilizar cada vez que desee utilizar las lentes en una mónada State.)

El data-lens-template el paquete puede ser la aplicación de Template Haskell que desee; Deriva definiciones de lentes para campos de registro.

El otro paquete de lentes populares es fclabels. Prefiero lente de datos por su simplicidad y velocidad; fclabels (a partir de la versión 1.0) es un poco más flexible, pero no necesita esa flexibilidad para lo que quiere hacer. (Tenga en cuenta que debido a su nueva flexibilidad, el tipo de etiquetas (:->) de fclabels ya no se puede traducir directamente a la definición simple de lentes, como se menciona en la respuesta de desbordamiento de pila que he vinculado)

1

Esto no es posible sin Template Haskell. Puede usar el acceso a datos y la plantilla de acceso a datos para eliminar dicha placa de la caldera.

+0

Creo que esto es correcto. La sintaxis de registro crea automáticamente * getters * para usted, pero esos son en su mayoría inútiles cuando usted quiere crear * setters *. –

Cuestiones relacionadas