मैं इसे आधा सच मानता हूं। हास्केल में अमूर्त करने की अद्भुत क्षमता है, और इसमें अनिवार्य विचारों पर अमूर्तता भी शामिल है। उदाहरण के लिए, हास्केल के पास लूप होते समय कोई अंतर्निहित अनिवार्यता नहीं है, लेकिन हम इसे लिख सकते हैं और अब यह करता है:
while :: (Monad m) => m Bool -> m () -> m ()
while cond action = do
c <- cond
if c
then action >> while cond action
else return ()
कई अनिवार्य भाषाओं के लिए अमूर्तता का यह स्तर कठिन है। यह अनिवार्य भाषाओं में किया जा सकता है जिनमें क्लोजर हैं; जैसे। अजगर और सी #।
लेकिन हास्केल में मोनाड कक्षाओं का उपयोग करते हुए अनुमत साइड-इफेक्ट को चिह्नित करने की अत्यधिक (अद्वितीय) क्षमता है । उदाहरण के लिए, यदि हमारे पास कोई फ़ंक्शन है:
foo :: (MonadWriter [String] m) => m Int
यह एक "जरूरी" कार्य हो सकता है, लेकिन हम जानते हैं कि यह केवल दो काम कर सकता है:
- "आउटपुट" तार की एक धारा
- एक Int लौटें
यह कंसोल पर प्रिंट नहीं कर सकता है या नेटवर्क कनेक्शन स्थापित नहीं कर सकता है, आदि को अमूर्त क्षमता के साथ जोड़कर, आप फ़ंक्शन लिख सकते हैं जो "किसी भी संगणना जो एक धारा का उत्पादन करता है" आदि पर कार्य करता है।
यह वास्तव में हास्केल की अमूर्त क्षमताओं के बारे में सब है जो इसे एक बहुत अच्छी अनिवार्य भाषा बनाता है।
हालांकि, झूठा आधा वाक्यविन्यास है। मुझे हस्केल सुंदर क्रिया और अजीब शैली में उपयोग करने के लिए अजीब लगता है। ऊपर दिए गए while
लूप का उपयोग करने के लिए यहां एक उदाहरण आवश्यक शैली की गणना है , जो एक लिंक की गई सूची के अंतिम तत्व को ढूंढती है:
lastElt :: [a] -> IO a
lastElt [] = fail "Empty list!!"
lastElt xs = do
lst <- newIORef xs
ret <- newIORef (head xs)
while (not . null <$> readIORef lst) $ do
(x:xs) <- readIORef lst
writeIORef lst xs
writeIORef ret x
readIORef ret
सभी कि IORef कचरा, डबल रीड, <$>
एक इनलाइन संगणना के परिणाम पर संचालित करने के लिए एक पढ़ने, fmapping ( ) के परिणाम को बांधने के लिए ... यह सब बहुत ही जटिल लग रही है। यह एक कार्यात्मक दृष्टिकोण से पूरी तरह से समझ में आता है, लेकिन अनिवार्य भाषाएं इनमें से अधिकांश विवरणों को गलीचा के नीचे स्वीप करती हैं ताकि उनका उपयोग करना आसान हो सके।
जाहिर है, शायद अगर हम एक अलग-अलग- while
शैली वाले कॉम्बिनेटर का उपयोग करते हैं तो यह क्लीनर होगा। लेकिन अगर आप उस दर्शन को पर्याप्त रूप से लेते हैं (स्पष्ट रूप से खुद को व्यक्त करने के लिए कॉम्बिनेटरों के एक समृद्ध सेट का उपयोग करके), तो आप फिर से कार्यात्मक प्रोग्रामिंग पर पहुंचते हैं। इम्पीरेटिव-स्टाइल हास्केल सिर्फ एक अच्छी तरह से डिज़ाइन की गई अनिवार्य भाषा की तरह "प्रवाह" नहीं करता है, जैसे कि अजगर।
अंत में, एक सिंटैक्टिक फेस-लिफ्ट के साथ, हास्केल सबसे अच्छी अनिवार्य भाषा हो सकती है। लेकिन, फेस लिफ्ट्स की प्रकृति से, यह आंतरिक रूप से सुंदर और वास्तविक के साथ बाहरी रूप से सुंदर और नकली कुछ की जगह लेगा।
संपादित करें : lastElt
इस अजगर लिप्यंतरण के साथ विपरीत :
def last_elt(xs):
assert xs, "Empty list!!"
lst = xs
ret = xs.head
while lst:
ret = lst.head
lst = lst.tail
return ret
लाइनों की समान संख्या, लेकिन प्रत्येक पंक्ति में थोड़ा कम शोर है।
EDIT 2
यह किस लिए लायक है, इस तरह हास्केल में एक शुद्ध प्रतिस्थापन दिखता है:
lastElt = return . last
बस। या, यदि आप मुझे उपयोग करने से मना करते हैं Prelude.last
:
lastElt [] = fail "Unsafe lastElt called on empty list"
lastElt [x] = return x
lastElt (_:xs) = lastElt xs
या, यदि आप चाहते हैं कि यह किसी भी Foldable
डेटा संरचना पर काम करे और यह पहचानें कि आपको वास्तव में त्रुटियों को संभालने की आवश्यकता नहीं है IO
:
import Data.Foldable (Foldable, foldMap)
import Data.Monoid (Monoid(..), Last(..))
lastElt :: (Foldable t) => t a -> Maybe a
lastElt = getLast . foldMap (Last . Just)
साथ Map
, उदाहरण के लिए:
λ➔ let example = fromList [(10, "spam"), (50, "eggs"), (20, "ham")] :: Map Int String
λ➔ lastElt example
Just "eggs"
(.)
ऑपरेटर है समारोह रचना ।