2012-01-26 7 views
17
isAlphaNum :: Char -> Bool 
isAlphaNum = (||) <$> isAlpha <*> isNum 

मैं देख सकता हूं कि यह काम करता है, लेकिन मुझे नहीं पता कि आवेदक (या फंक्टर) के उदाहरण कहां से आते हैं।क्या कोई इस बात में समझा सकता है कि इस कोड में लागू उदाहरण कहां से उत्पन्न होते हैं?

क्या फ़ंक्शंस को मुक्त करने के लिए इस तरह के प्रयासों पर जाना आम बात है?

+1

'isAlphaNum' ==' (\ c-> ((||) .isAlpha) c (isNum c)) '==' (\ c-> isAlpha c || isNum c) '(... बस एक sidenote)। –

उत्तर

18

यह Applicative उदाहरण ((->) r) के लिए एक सामान्य प्रकार से कार्य करता है। यह उन सभी के लिए उपयोग करने के लिए एक तर्क को डुप्लिकेट करके एक ही फ़ंक्शन में समान तर्क प्रकार के साथ फ़ंक्शंस को जोड़ता है। (<$>) समारोह रचना है, शुद्ध const है, और यहाँ क्या (<*>) करने के लिए अनुवाद है:

s :: (r -> a -> b) -> (r -> a) -> r -> b 
s f g x = f x (g x) 

यह समारोह शायद बेहतर the S combinator के रूप में जाना जाता है।

((->) r) functor भी Reader इकाई है, जहां साझा तर्क "पर्यावरण" मूल्य है, उदाहरण के लिए है:

newtype Reader r a = Reader (r -> a) 

मैं इसे बनाने के लिए यह करने के लिए आम नहीं कहेंगे फंक्शंस पॉइंट-फ्री, लेकिन कुछ मामलों में यह वास्तव में मुहावरे में इस्तेमाल होने के बाद स्पष्टता में सुधार कर सकता है। उदाहरण के लिए, उदाहरण के लिए, मैं बहुत आसानी से पढ़ सकता हूं "अर्थ एक अक्षर या संख्या है"।

+0

रों च जी एक्स = रों एक्स (छ एक्स) होना चाहिए रों च जी एक्स = च एक्स (छ एक्स) – hvintus

+0

@hvintus: ओह, टाइपो। धन्यवाद! –

7

आपको Control.Applicative पैकेज से मुक्त करने के लिए स्थिर तीर कहा जाता है (कॉनोर मैकब्राइड एट अल द्वारा "प्रभाव के साथ आवेदक प्रोग्रामिंग" देखें) के उदाहरण प्राप्त होते हैं। इसलिए, आपके मामले में Char में कोई भी स्रोत प्रकार, एक आवेदक उदाहरण को जन्म देता है जहां कोई अन्य प्रकार aChar -> a प्रकार से मैप किया गया है।

जब आप इनमें से किसी भी गठबंधन, एक मूल्य के x :: Char -> a करने के लिए एक समारोह f :: Char -> a -> b लागू कहते हैं, अर्थ है कि आप एक नया कार्य Char -> b, जो दोनों f और x इसलिए की तरह में अपने तर्क फीड होगा, बनाने है

f <*> x = \c -> (f c) (x c) 

इसलिए, के रूप में आप का कहना है, इस

isAlphaNum c = (isAlpha c) || (isNum c) 

करने के लिए अपने उदाहरण बराबर मेरी राय में बना देता है, इस तरह के प्रयास हमेशा जरूरी नहीं है, और यह अच्छा लगेगा यदि हास्केल के पास आवेदकों के लिए बेहतर वाक्य रचनात्मक समर्थन था (शायद 2-स्तर की भाषाओं की तरह कुछ)।

3

यह ध्यान दिया जाना चाहिए कि लिफ्ट कार्यों का उपयोग करके आपको एक समान प्रभाव मिलता है, उदा।:

import Data.Char 
import Control.Applicative 

isAlphaNum = liftA2 (||) isAlpha isNumber 

या, की इकाई उदाहरण का उपयोग करते हुए ((->) आर) अनुप्रयोगी एक के बजाय:

import Data.Char 
import Control.Monad 

isAlphaNum = liftM2 (||) isAlpha isNumber 

[विषयांतर]

अब जब कि तुम जानते हैं कि कैसे करने के लिए एक द्विआधारी कार्य करने के लिए एक तर्क करने के लिए दो मध्यवर्ती कार्य करता है और परिणाम वितरित करना, किसी भी तरह से संबंधित मामले कि आप distrib करना चाहते है एक मध्यवर्ती कार्य करने के लिए उटे दो तर्कों और एक द्विआधारी समारोह के लिए परिणाम:

import Data.Function 

orFst = (||) `on` fst 

-- orFst (True,3) (False, 7) 
--> True 

यह पैटर्न उदा है अक्सर compare फ़ंक्शन के लिए उपयोग किया जाता है।

+2

'कंट्रोल.कॉन्केनेनेटिव' भी है जो कुछ मानक कॉन्सटेनेटिव संयोजक को हास्केल में लाता है। आपके उदाहरण भी 'द्वि है अल्लाफा नम्बर (||)' और 'fst \' biAp \ '(||) 'हो सकता है। यह जरूरी नहीं दिखाता है, लेकिन 'Control.Concatenative' कई बिंदु-मुक्त अभिव्यक्तियों के लिए सुगमता में सुधार करने में मदद करता है, क्योंकि, यह है कि यह समेकित प्रोग्रामिंग क्या है। –

+0

धन्यवाद, मुझे इस मॉड्यूल को देखना है ... – Landei

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