如何在haskell中“解包”一个结构

时间:2009-12-20 00:28:00

标签: haskell struct ffi

我最近遇到了这个问题并找到了解决方案,但我想知道是否有更好的(或更恰当的)解决方案。

我有一个颜色结构:

data Rgb = Rgb Double Double Double

还有一个函数我想将颜色组件分别传递给开罗:

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

所以我需要以某种方式“解包”此数据结构,因为setSourceRGB不会使用Rgb。我找到了两种方法。一种是定义一个函数来应用Rgb

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

然后我可以做:

applyRgb setSourceRGB rgb

我提出的另一种方法是使用case进行内联lambda表达式,这意味着我不必定义单独的函数:

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

我对此并不完全满意,但是以某种方式应用函数只是传递一些值似乎并不正确。我希望能够将其翻转,并将Rgb“转换”为setSourceRGB的正确类型。不幸的是,在我看来,这是不可能有一个功能

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

可以传递给setSourceRGB。也许applyRgb是最好的解决方案,但我想知道是否有更好的方法可以让我表达出来:

setSourceRGB (fromRgb rgb)

3 个答案:

答案 0 :(得分:4)

顺便说一下,你几乎可以肯定:

data Rgb = Rgb !Double !Double !Double

而是使用-funbox-strict-fields进行编译,因此可以将组件解压缩为无分配的原始double值。

答案 1 :(得分:3)

不,你不能写类似setSourceRGB(fromRgb rgb)的东西,因为它只会给函数一个参数,所以applyRgb似乎是最好的解决方案。 如果你喜欢这种东西,你也可以使用applyRgb作为中缀函数:

setSource `applyRgb` rgb

如果您经常使用此功能,则可以通过为applyRgb setSource定义名称来使代码更易于阅读。

答案 2 :(得分:2)

你不能将任何东西“解包”成多个参数而不用你想象的方式包装函数本身。

但是,为了保持一致性,我可能会给这样的助手命名。

-- 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