Как “распаковать” структуру в 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

Иначе я придумал, должен сделать встроенное лямбда-выражение со случаем, что означает, что я не должен определять отдельную функцию:

(\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)
10
задан Don Stewart 18 April 2011 в 18:26
поделиться

3 ответа

Нет, вы не можете написать что-то вроде setSourceRGB (fromRgb rgb), потому что он просто даст один аргумент функции, поэтому applyRgb кажется лучшим решением. Если вам нравятся такие вещи, вы также можете использовать applyRgb как инфиксную функцию:

setSource `applyRgb` rgb

Если вы часто используете эту функцию, вы можете упростить чтение кода, указав имя для applyRgb setSource.

3
ответ дан 4 December 2019 в 01:57
поделиться

Вы не можете «распаковать» что-либо в несколько аргументов, не обернув саму функцию способами, которые вы выяснили.

Однако для единообразия я бы, наверное, назвал помощник что-то вроде этого.

-- 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
2
ответ дан 4 December 2019 в 01:57
поделиться

Кстати, вы почти наверняка должны иметь:

data Rgb = Rgb !Double !Double !Double

вместо этого и скомпилировать с -funbox-strict-fields, чтобы компоненты можно было распаковать в свободное от размещения примитивные значения типа double.

4
ответ дан 4 December 2019 в 01:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: