2011-08-11 10 views
10

मेरे पास एक प्रकार Image है जो मूल रूप से फ्लोट की सी-सरणी है। जैसे map :: (Float -> Float) -> Image -> Image, या zipWith :: (Float -> Float -> Float) -> Image -> Image -> Image जैसे कार्यों को बनाना आसान है।एक मजेदार के बिना आवेदक

हालांकि, मुझे एहसास है कि इन कार्यों के शीर्ष पर एक आवेदक उदाहरण की तरह दिखने वाला कुछ भी प्रदान करना संभव होगा, जिससे ((+) <$> image1 <*> image2) या ((\x y z -> (x+y)/z) <$> i1 <*> i2 <*> i3) जैसे अधिक लचीले पिक्सेल स्तर में हेरफेर की अनुमति मिल सके। हालांकि, निष्पक्ष दृष्टिकोण विफल रहता है, क्योंकि छवि प्रकार में फ्लोट्स के अलावा अन्य चीजें नहीं हो सकती हैं, जिससे fmap को कार्यान्वित करना असंभव हो जाता है।

इसे कैसे लागू किया जा सकता है?

+3

क्यों आप छवि को फ्लोट के अलावा अन्य चीज़ों को शामिल करने की अनुमति नहीं देंगे? निश्चित रूप से, आपका 'प्रदर्शन :: छवि फ़्लोट -> आईओ() 'केवल फ्लोट के साथ छवियां ले सकता है, लेकिन अन्य कार्यों जैसे' मानचित्र 'के लिए इससे कोई फर्क नहीं पड़ता। –

+1

छवि प्रकार एक सी सरणी है जिसे रूपांतरणों में बहुत अधिक समय व्यतीत किए बिना सी कार्यों में पारित करने की आवश्यकता होती है। साथ ही, मुझे लगता है कि अगर यह कामों की तरह चीजें पकड़ सकता है, तो 'शुद्ध' पर कॉल करने के बाद कुछ मिलियन आंशिक रूप से मूल्यांकन किए गए कार्यों के बजाय बदसूरत प्रदर्शन-वार होगा। (कार्यों की छवि रखने के द्वारा 'शुद्ध' को कार्यान्वित करना भी समस्याग्रस्त है क्योंकि यह छवि के आकार को नहीं जान सकता है।) – aleator

+0

क्या आप अपना प्रकार 'प्रकार छवि = कैरे फ़्लोट' जैसे परिभाषित कर सकते हैं और एफएमएपी के साथ कैरे के लिए फ़ंक्शन उदाहरण बना सकते हैं आपका नक्शा फ़ंक्शन होने के नाते, और आप सुनिश्चित करते हैं कि आप किसी भी चीज का कैरे नहीं बना सकते हैं लेकिन कैरे फ़्लोट (उदाहरण के लिए, कन्स्ट्रक्टर को निर्यात न करें) –

उत्तर

15

टिप्पणियां पढ़ना, मुझे थोड़ा चिंता है कि आकार यहां कालीन के नीचे है। क्या आकार खराब होने पर एक समझदार व्यवहार है?

इस बीच, कुछ ऐसी चीजें हो सकती हैं जो आप निम्नलिखित पंक्तियों के साथ समझदारी से कर सकते हैं। यहां तक ​​कि यदि आपके सरणी पॉलिमॉर्फिक बनाने में आसान नहीं हैं, तो आप इस तरह के Applicative उदाहरण बना सकते हैं।

data ArrayLike x = MkAL {sizeOf :: Int, eltOf :: Int -> x} 

instance Applicative ArrayLike where 
    pure x     = MkAL maxBound (pure x) 
    MkAL i f <*> MkAL j g = MkAL (min i j) (f <*> g) 

(उत्साही नोट करेंगे कि मैं (maxBound, min) monoid से प्रेरित है कि साथ (Int ->) अनुप्रयोगी के उत्पाद कर लिया है।)

आप एक साफ पत्राचार कर सका

imAL :: Image -> ArrayLike Float 
alIm :: ArrayLike Float -> Image 
प्रक्षेपण और सारणीकरण द्वारा

? यदि ऐसा है, तो आप इस तरह कोड लिख सकते हैं।

alIm $ (f <$> imAL a1 <*> ... <*> imAL an) 

इसके अलावा, अगर आप तो, उस पैटर्न लपेट के लिए एक ओवरलोड ऑपरेटर के रूप में

imapp :: (Float -> ... -> Float) -> (Image -> ... -> Image) 

चाहते हैं कि उसे typeclass प्रोग्रामिंग में एक मानक व्यायाम है! (पूछें कि आपको अधिक संकेत की आवश्यकता है या नहीं।)

महत्वपूर्ण बिंदु यह है कि रैपिंग रणनीति का मतलब है कि आपको शीर्ष पर कार्यात्मक अधिरचना लगाने के लिए अपने सरणी संरचनाओं के साथ बंदर की आवश्यकता नहीं है।

+0

बढ़िया! काफी वही है जो मैं खोज रहा था। यह पता नहीं लगा सकता कि मैंने इसे खुद क्यों नहीं देखा। क्या आपका मतलब एन अलग-अलग धैर्य कार्यों के लिए एन उदाहरण बनाना है, या टाइपक्लास टिप्पणी द्वारा कुछ और चालाक है? – aleator

+2

आपको केवल दो उदाहरणों की आवश्यकता होनी चाहिए: arity 0 के लिए आधार केस (या 1 यदि आपको आउटपुट के आकार को बाध्य करने के लिए एक सरणी इनपुट की आवश्यकता है), और एक चरण केस। रुको (माफ करना कोड टिप्पणियों में गड़बड़ है) ... 'कक्षा NAry एफएफ फाई | एफएफ -> फाई, फाई -> एफएफ जहां {naryHelp :: (ArrayLike (फ्लोट -> एफएफ)) -> (छवि -> फाई); नारी :: (फ्लोट -> एफएफ) -> (छवि -> फाई); nary = naryHelp। शुद्ध} ; उदाहरण नरी फ्लोट छवि जहां {naryHelp f i = alIm $ f <*> imAL i}; उदाहरण NAry ff fi => NAry (Float -> ff) (छवि -> fi) जहां {naryHelp fi = naryHelp (f <*> imAL i)} ' – pigworker

+1

बस एक अतिरिक्त विचार: 'ArrayLike' मूल रूप से रेपा देरी वाली सरणी की तरह है , सही? कम से कम यह देखने के लिए सादा है कि मैं आसानी से 'alIm' में समांतर कंप्यूटेशंस कैसे सम्मिलित कर सकता हूं और' बल 'को' imAl 'के रूप में परिभाषित कर सकता हूं। alIm'। – aleator

6

आप छवि में पिक्सेल पर संचालन करने की अपेक्षा कैसे करेंगे? यही है, ((+) <$> image1 <*> image2) के लिए, क्या आप हास्केल में सभी परिचालन करना चाहते हैं और एक नई परिणामी छवि का निर्माण करना चाहते हैं, या आपको सभी प्रसंस्करण करने के लिए सी फ़ंक्शंस को कॉल करना होगा?

यदि यह पूर्व है, तो पिगवर्कर का जवाब वह दृष्टिकोण है जो मैं लेता हूं।

यदि इसके बजाय यह आवश्यक है कि सभी छवि कुशलताएं सी के माध्यम से संभाली जाए, तो संचालन का प्रतिनिधित्व करने के लिए एक छोटा डीएसएल कैसे बनाया जाए?

+0

छवि को ज्यादातर सी द्वारा छेड़छाड़ की जाएगी। मैं बाद में हैकेल में सरल पिक्सेल स्तर के संचालन करने का एक तरीका है - यह एटान 2 जैसे सरल कार्य को जोड़ने के लिए सी को सभी तरह से छोड़ने के लिए थकाऊ है। – aleator

6

यदि आप Float से "पिक्सेल" प्रकार सामान्यीकरण और परिमित & असतत डोमेन (सरणियों) से विस्तार & निरंतर डोमेन अनंत एक बहुत अधिक compositional Image प्रकार मिल जाएगा। इन सामान्यीकरणों के प्रदर्शन के रूप में, पेपर Functional Images और example images की परिमित नमूना (संबंधित नमूना) देखें। परिणामस्वरूप, आपको Monoid, Functor, Applicative, Monad, और Comonad के उदाहरण मिलते हैं। इसके अलावा, इन उदाहरणों का अर्थ पूरी तरह से कार्यों के लिए संबंधित उदाहरणों द्वारा निर्धारित किया जाता है, जो टाइप क्लास morphisms के सिद्धांत को संतुष्ट करते हैं, जैसा पेपर Denotational design with type class morphisms में वर्णित है। उस पेपर की धारा 13.2 संक्षेप में इमेजरी का वर्णन करती है।