2009-12-20 14 views
10

Hace poco encontré este problema y encontré una solución, pero me pregunto si hay soluciones mejores (o simplemente más idiomáticas).Cómo "descomprimir" una estructura en haskell

tengo una estructura para un color:

data Rgb = Rgb Double Double Double 

y hay una función que me gustaría pasar a los componentes de color de forma individual, en realidad de El Cairo:

setSourceRGB :: Double -> Double -> Double -> Render() 

Así que necesito para "descomprimir" esta estructura de datos de alguna manera, ya que setSourceRGB no toma un Rgb. Encontré dos maneras. Uno de ellos es definir una función para aplicar el contenido de un Rgb:

applyRgb :: (Double -> Double -> Double -> t) -> Rgb -> t 
applyRgb f (Rgb r g b) = f r g b 

Entonces puedo hacer:

applyRgb setSourceRGB rgb 

Otra forma que se me ocurrió es hacer una expresión en línea lambda con un caso, lo que significa que no tiene que definir una función separada:

(\z -> (case z of (Rgb r g b) -> setSourceRGB r g b)) rgb 

sin embargo no estoy completamente contento con esto, de alguna manera la aplicación de una función sólo para pasar algunos valores no me parece bien. Me gustaría poder darle la vuelta, y "convertir" el Rgb al tipo correcto para setSourceRGB. Por desgracia, me parece que eso es imposible tener una función

fromRgb :: Rgb -> Double -> Double -> Double 

que se puede pasar a setSourceRGB. Tal vez applyRgb es la mejor solución, pero me pregunto si hay alguna manera mejor que me permita expresar como:

setSourceRGB (fromRgb rgb) 
+3

¿Qué pasa con el 'case .. of'? '(\ (Rgb r g b) -> SetSource r g b) rgb' – ephemient

Respuesta

3

No, no se puede escribir algo como setSourceRGB (fromRgb RGB), ya que se solo dale un argumento a la función, entonces applyRgb parece ser la mejor solución. Si te gusta este tipo de cosas, también se puede utilizar applyRgb como una función infija:

setSource `applyRgb` rgb 

Si a menudo se utiliza esta función, su puede hacer que su código sea más fácil de leer mediante la definición de un nombre para applyRgb setSource.

4

Por cierto, se debe casi seguro que tienen:

data Rgb = Rgb !Double !Double !Double 

lugar, y compilar con -funbox-estricta campos, por lo que los componentes pueden ser desempaquetado en valores dobles primitivos sin asignación.

2

No se puede "descomprimir" nada en múltiples argumentos sin ajustar la función en sí misma de la forma que se ha imaginado.

Sin embargo, para ser consistentes, probablemente le pondría al ayudante algo como esto.

-- from Prelude... 
uncurry :: (a -> b -> c) -> (a, b) -> c 
uncurry f (a, b) = f a b 

-- yours? 
uncurryRgb :: (Double -> Double -> Double -> a) -> Rgb -> a 
uncurryRgb f (Rgb r g b) = f r g b 
+0

Debe corregir la definición para que coincida con la firma. En este momento, los casos son diferentes. – Martijn

+0

Augh, typo. Bueno, aparte de las diferencias ortográficas, esta es la misma definición que OP 'applyRgb' ... – ephemient

Cuestiones relacionadas