【问题标题】:How to "unpack" a structure in haskell如何在haskell中“解包”结构
【发布时间】:2009-12-20 00:28:00
【问题描述】:

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

我有一个颜色的结构:

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)

【问题讨论】:

  • case .. of 是怎么回事? (\(Rgb r g b) -> SetSource r g b) rgb

标签: haskell struct ffi


【解决方案1】:

顺便说一句,你几乎肯定应该有:

data Rgb = Rgb !Double !Double !Double

改为使用 -funbox-strict-fields 进行编译,因此可以将组件解压缩为无需分配的原始双精度值。

【讨论】:

    【解决方案2】:

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

    setSource `applyRgb` rgb
    

    如果您经常使用此函数,您可以通过为 applyRgb setSource 定义一个名称来使您的代码更易于阅读。

    【讨论】:

      【解决方案3】:

      如果不按照你想出的方式包装函数本身,你就不能将任何东西“解包”成多个参数。

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

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

      【讨论】:

      • 您应该修复定义以匹配签名。现在情况有所不同。
      • 啊,错字了。好吧,撇开拼写差异不谈,这与 OP 的 applyRgb 定义相同...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-13
      相关资源
      最近更新 更多