如何“拆包” Haskell 中的结构
我最近遇到了这个问题并找到了解决方案,但我想知道是否有更好的(或更惯用的)解决方案。
我有一个颜色的结构:
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)
I recently came across this problem and found a solution but I'm wondering if there are better (or just more idiomatic) solutions.
I have a structure for a colour:
data Rgb = Rgb Double Double Double
And there is a function I'd like to pass the colour components to individually, actually from Cairo:
setSourceRGB :: Double -> Double -> Double -> Render ()
So I need to "unpack" this data structure somehow, since setSourceRGB
doesn't take an Rgb
. I found two ways. One is to define a function to apply the contents of an Rgb
:
applyRgb :: (Double -> Double -> Double -> t) -> Rgb -> t
applyRgb f (Rgb r g b) = f r g b
Then I can do:
applyRgb setSourceRGB rgb
Another way I came up with is to do an inline lambda expression with a case, which means I don't have to define a separate function:
(\z -> (case z of (Rgb r g b) -> setSourceRGB r g b)) rgb
I'm not completely happy with this however, somehow applying a function just to pass some values doesn't seem right. I'd like to be able to turn it around, and "convert" the Rgb
to the right type for setSourceRGB
. Unfortunately it seems to me that's it's impossible to have a function
fromRgb :: Rgb -> Double -> Double -> Double
that can be passed to setSourceRGB
. Perhaps applyRgb
is the best solution, but I'm wondering if there's some better way that will let me express it as:
setSourceRGB (fromRgb rgb)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
顺便说一句,你几乎肯定应该有:
相反,并使用 -funbox-strict-fields 进行编译,以便可以将组件解包为免分配的原始双精度值。
BTW, you should almost certainly have:
instead, and compile with -funbox-strict-fields, so the components can be unpacked into allocation-free primitive double values.
不,你不能写像 setSourceRGB (fromRgb rgb) 这样的东西,因为它只会给函数一个参数,所以 applyRgb 似乎是最好的解决方案。
如果你喜欢这种东西,你也可以使用 applyRgb 作为中缀函数:
如果你经常使用这个函数,你可以通过为 applyRgb setSource 定义一个名称来使你的代码更容易阅读。
No, you can't write something like setSourceRGB (fromRgb rgb), because it will just give one argument to the function, so applyRgb seems like the best solution.
If you like this sort of thing, you can also use applyRgb as an infix function :
If you often use this function, your can make your code easier to read by defining a name for applyRgb setSource.
如果不按照您想出的方式包装函数本身,您就无法将任何内容“解包”到多个参数中。
但是,为了保持一致性,我可能会将助手命名为这样的名称。
You can't "unpack" anything into multiple arguments without wrapping the function itself the ways you've figured out.
However, for consistency, I'd probably name the helper something like this.