2012-11-18 8 views
29
import Control.Applicative 

main = print $ fmap (*2) (1,2) 

(1,4) उत्पन्न करता है। मैं उम्मीद करता हूं कि यह (2,4) का उत्पादन करे, लेकिन इसके बजाय फ़ंक्शन केवल टुपल के दूसरे तत्व पर लागू होता है।2-ट्यूपल फ़ंक्शन उदाहरण केवल दूसरे तत्व पर फ़ंक्शन को क्यों लागू करता है?

अद्यतन मैंने मूल रूप से लगभग सीधे इसे बाहर निकाला है। मैं एक मिनट में अपना उत्तर पोस्ट करूंगा ..

उत्तर

12

Functor उदाहरण वास्तव में GHC.Base मॉड्यूल से है जो Control.Applicative द्वारा आयात किया जाता है।

उदाहरण को लिखने की कोशिश कर रहा है, मैं देख सकता हूं कि यह काम नहीं करेगा, tuples की परिभाषा के बाद; उदाहरण के लिए केवल एक प्रकार पैरामीटर की आवश्यकता होती है, जबकि 2-टुपल में दो होते हैं।

एक वैध Functor उदाहरण कम से कम, (a,a) प्रत्येक तत्व के लिए एक ही प्रकार है कि tuples पर होना करने के लिए होता है, लेकिन आप कुछ भी डरपोक नहीं कर सकते, पर उदाहरण परिभाषित की तरह:

type T2 a = (a,a) 

क्योंकि उदाहरण के प्रकार समानार्थी होने की अनुमति नहीं है।

ऊपर प्रतिबंधित 2-टपल पर्याय तार्किक प्रकार के रूप में एक ही है:

data T2 a = T2 a a 

जो एक functor उदाहरण हो सकता है:

instance Functor T2 where 
    fmap f (T2 x y) = T2 (f x) (f y) 

के रूप में गेब्रियल टिप्पणी में टिप्पणी की इस, ब्रांचिंग संरचनाओं या समरूपता के लिए उपयोगी हो सकता है। के लिए कौन सा उत्पादन आप उम्मीद करते हैं:

+8

दरअसल, यह मज़ेदार वर्ग के उदाहरण के रूप में उपयोगी है। उदाहरण के लिए, मैं एक पेड़ को 'टाइप ट्री ए = फ्री टी 2 ए' के ​​रूप में परिभाषित कर सकता हूं। वास्तव में, उस प्रकार के अधिकांश उपयोग (एक मज़ेदार के रूप में इसकी क्षमता में) में कुछ प्रकार की शाखा या समेकन शामिल है। –

+12

यह उल्लेखनीय है कि यदि आप टुपल के किस हिस्से को मानचित्र पर निर्दिष्ट करना चाहते हैं, तो आप 'Control.Lens' का उपयोग कर सकते हैं। एक 'सेटर' एक' फंक्टर 'उदाहरण जैसा है जिसे आप स्पष्ट रूप से निर्दिष्ट करते हैं, इसलिए '_1 (+1) (5,3)' ==> '(6,3)'; '_2 (* 2) (" मजाकिया, 2) '==>' ("मजेदार", 4) '; दोनों लंबाई (" हाय "," वहां ") '==>' (2,5) ';' ओवर (दोनों ._1) (* 10) ((1,2), (3,4)) '==>' ((10,2), (30,4)) ' – shachaf

+0

धन्यवाद @ शचाफ , यह एक उपयोगी टिप्पणी है। –

29

मुझे एक प्रश्न के साथ इस का जवाब दें

main = print $ fmap (*2) ("funny",2) 

आप के रूप में आप (data Pair a = Pair a a या तो उपयोग करते हुए) चाहते हैं कुछ है सकते हैं, लेकिन (,) के रूप में विभिन्न प्रकार के हो सकता है उनका पहला और दूसरा तर्क, आप भाग्य से बाहर हैं।

7

जोड़े, अनिवार्य रूप से, इस तरह परिभाषित कर रहे हैं:

data (,) a b = (,) a b 

Functor वर्ग इस तरह दिखता है:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

समारोह तर्क और परिणाम के प्रकार के बाद से तरह * होना आवश्यक है (यानी वे प्रतिनिधित्व करते हैं उन कार्यों को टाइप करने के बजाय मूल्य जिन्हें आगे या अधिक विदेशी चीजों को लागू किया जा सकता है), हमारे पास a :: *, b :: * होना चाहिए, और सबसे महत्वपूर्ण बात यह है कि हमारे उद्देश्यों के लिए f :: * -> * । चूंकि (,) में * -> * -> * है, इसलिए Functor होने के लिए उपयुक्त प्रकार प्राप्त करने के लिए इसे * पर लागू किया जाना चाहिए। इस प्रकार

instance Functor ((,) x) where 
    -- fmap :: (a -> b) -> (x,a) -> (x,b) 

तो वहाँ वास्तव में कोई रास्ता नहीं एक Functor उदाहरण कुछ और करने में लिखने के लिए है।


एक उपयोगी वर्ग कि Data.Bifunctor से जोड़े के साथ काम करने के कई तरीके प्रदान करता है Bifunctor है।

class Bifunctor f where 
    bimap :: (a -> b) -> (c -> d) -> f a c -> f b d 
    bimap f g = first f . second g 

    first :: (a -> b) -> f a y -> f b y 
    first f = bimap f id 

    second :: (c -> d) -> f x c -> f x d 
    second g = bimap id g 

यह आपको (Data.Bifunctor.Join से) निम्नलिखित जैसी चीजों के बारे में कर सकते हैं:

newtype Join p a = 
    Join { runJoin :: p a a } 

    instance Bifunctor p => Functor (Join p) where 
    fmap f = Join . bimap f f . runJoin 

Join (,) तो अनिवार्य रूप से, Pair, जहां

data Pair a = Pair a a 
बेशक

रूप में ही है आप भी कर सकते हैं जोड़े के साथ काम करने के लिए बस Bifunctor उदाहरण का उपयोग करें।

+0

'' - fmap :: (a -> b) -> (y, x, a) -> (वाई, एक्स, बी) '3-टुपल्स के लिए काम नहीं कर रहा है? –

संबंधित मुद्दे