2009-12-20 31 views
10

Gần đây tôi đã gặp vấn đề này và tìm thấy một giải pháp nhưng tôi tự hỏi nếu có tốt hơn (hoặc chỉ là thành ngữ) các giải pháp.Làm thế nào để "giải nén" một cấu trúc trong haskell

Tôi có một cấu trúc cho một màu sắc:

data Rgb = Rgb Double Double Double 

Và có một chức năng tôi muốn vượt qua các thành phần màu sắc cho cá nhân, thực sự từ Cairo:

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

Vì vậy, tôi cần để "giải nén" cấu trúc dữ liệu này bằng cách nào đó, vì setSourceRGB không mất Rgb. Tôi tìm thấy hai cách. Một là để xác định một chức năng để áp dụng các nội dung của một Rgb:

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

Sau đó, tôi có thể làm:

applyRgb setSourceRGB rgb 

Một cách khác tôi đã đưa ra là để làm một biểu thức inline lambda với một trường hợp, có nghĩa là tôi không cần phải xác định một chức năng riêng biệt:

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

tôi không hoàn toàn hài lòng với điều này tuy nhiên, bằng cách nào đó áp dụng một chức năng chỉ để vượt qua một số giá trị có vẻ không đúng. Tôi muốn có thể biến nó xung quanh và "chuyển đổi" Rgb thành loại phù hợp cho setSourceRGB. Rất tiếc, có vẻ như tôi không thể có chức năng

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

có thể được chuyển đến setSourceRGB. Có lẽ applyRgb sự là giải pháp tốt nhất, nhưng tôi tự hỏi nếu có một cách nào đó tốt hơn mà sẽ cho phép tôi thể hiện nó như:

setSourceRGB (fromRgb rgb) 
+3

Điều gì xảy ra với 'trường hợp .. của'? '(\ (Rgb r g b) -> SetSource r g b) rgb' – ephemient

Trả lời

3

Không, bạn không thể viết một cái gì đó giống như setSourceRGB (fromRgb rgb), bởi vì nó sẽ chỉ cần đưa ra một đối số cho hàm, do đó, applyRgb có vẻ như là giải pháp tốt nhất. Nếu bạn thích các loại điều này, bạn cũng có thể sử dụng applyRgb như một chức năng ghi vào:

setSource `applyRgb` rgb 

Nếu bạn thường xuyên sử dụng chức năng này, bạn có thể làm cho mã của bạn dễ đọc hơn bằng cách định nghĩa một tên cho applyRgb setSource.

4

BTW, bạn gần như chắc chắn phải có:

data Rgb = Rgb !Double !Double !Double 

thay vào đó, và biên dịch với -funbox-nghiêm ngặt-lĩnh vực, vì vậy các thành phần có thể được giải nén vào giá trị tăng gấp đôi nguyên thủy phân bổ miễn phí.

2

Bạn không thể "giải nén" mọi thứ thành nhiều đối số mà không tự gói chính chức năng theo cách bạn đã tìm ra.

Tuy nhiên, để nhất quán, tôi có thể đặt tên cho người trợ giúp như thế này.

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

Bạn nên sửa định nghĩa để khớp với chữ ký. Ngay bây giờ các trường hợp khác nhau. – Martijn

+0

Augh, typo. Vâng, khác biệt chính tả sang một bên, đây là định nghĩa tương tự như OP 'applyRgb' ... – ephemient

Các vấn đề liên quan