खोज…


टिप्पणियों

हास्केल लोगो

हास्केल एक उन्नत विशुद्ध रूप से कार्यात्मक प्रोग्रामिंग भाषा है।

विशेषताएं:

  • वैधानिक रूप से टाइप किया गया: हास्केल में प्रत्येक अभिव्यक्ति का एक प्रकार होता है जो संकलन समय पर निर्धारित होता है। स्टेटिक टाइप चेकिंग प्रोग्राम के टेक्स्ट (सोर्स कोड) के विश्लेषण के आधार पर प्रोग्राम की टाइप सेफ्टी को वेरिफाई करने की प्रक्रिया है। यदि कोई प्रोग्राम स्टैटिक टाइप चेकर से गुजरता है, तो प्रोग्राम को सभी संभावित इनपुट के लिए कुछ प्रकार के सुरक्षा गुणों को संतुष्ट करने की गारंटी है।
  • विशुद्ध रूप से कार्यात्मक : हास्केल में प्रत्येक फ़ंक्शन गणितीय अर्थों में एक फ़ंक्शन है। कोई वक्तव्य या निर्देश नहीं हैं, केवल वे अभिव्यक्तियाँ हैं जो चर (स्थानीय या वैश्विक) को परिवर्तित नहीं कर सकते हैं और न ही समय या यादृच्छिक संख्या जैसी स्थिति का उपयोग कर सकते हैं।
  • समवर्ती: इसका प्रमुख संकलक, जीएचसी, एक उच्च-प्रदर्शन समानांतर कचरा कलेक्टर और हल्के वजन वाली संगोष्ठी पुस्तकालय के साथ आता है जिसमें कई उपयोगी संगामिति आदिम और अमूर्त होते हैं।
  • आलसी मूल्यांकन: कार्य उनके तर्कों का मूल्यांकन नहीं करते हैं। किसी अभिव्यक्ति के मूल्यांकन की तब तक देरी करता है जब तक कि उसके मूल्य की आवश्यकता न हो।
  • सामान्य-उद्देश्य: हास्केल का उपयोग सभी संदर्भों और वातावरण में किया जाता है।
  • पैकेज: सार्वजनिक पैकेज सर्वर पर उपलब्ध पैकेज की एक विस्तृत श्रृंखला के साथ हास्केल में ओपन सोर्स योगदान बहुत सक्रिय है।

हास्केल का नवीनतम मानक हास्केल 2010 है। मई 2016 तक, एक समूह अगले संस्करण, हास्केल 2020 पर काम कर रहा है।

आधिकारिक हास्केल प्रलेखन भी एक व्यापक और उपयोगी संसाधन है। किताबें, पाठ्यक्रम, ट्यूटोरियल, मैनुअल, गाइड आदि खोजने के लिए बढ़िया जगह।

संस्करण

संस्करण रिलीज़ की तारीख
हास्केल 2010 2012-07-10
हास्केल 98 2002/12/01

नमस्ते दुनिया!

एक बुनियादी "हैलो, दुनिया!" हास्केल में कार्यक्रम केवल एक या दो लाइनों में संक्षिप्त रूप से व्यक्त किया जा सकता है:

main :: IO ()
main = putStrLn "Hello, World!"

पहली पंक्ति एक वैकल्पिक प्रकार का एनोटेशन है, जो दर्शाता है कि main प्रकार IO () का एक मूल्य है, एक I / O क्रिया का प्रतिनिधित्व करता है, जो "मान" प्रकार का मूल्य () (पढ़ें "इकाई";) खाली ट्यूपल कोई जानकारी बताए; बाहरी दुनिया पर कुछ साइड इफेक्ट्स करने के अलावा (यहां, टर्मिनल पर एक स्ट्रिंग प्रिंट करना)। इस प्रकार का एनोटेशन आमतौर पर main लिए छोड़ा जाता है क्योंकि यह इसका एकमात्र संभव प्रकार है।

इसे एक helloworld.hs फ़ाइल में डालें और एक Haskell संकलक का उपयोग करके संकलित करें, जैसे GHC:

ghc helloworld.hs

संकलित फ़ाइल को निष्पादित करने के परिणामस्वरूप आउटपुट "Hello, World!" स्क्रीन पर मुद्रित किया जा रहा है:

./helloworld
Hello, World!

वैकल्पिक रूप से, runhaskell या runghc इसे संकलित किए बिना प्रोग्राम को व्याख्यायित मोड में चलाना संभव runghc है:

runhaskell helloworld.hs

संकलित करने के बजाय इंटरैक्टिव REPL का भी उपयोग किया जा सकता है। यह ज्यादातर हास्केल वातावरण के साथ भेज दिया जाता है, जैसे कि ghci जो जीएचसी संकलक के साथ आता है:

ghci> putStrLn "Hello World!"
Hello, World!
ghci> 

वैकल्पिक रूप से, लोड (या :l ) का उपयोग करके एक फ़ाइल से ghci में स्क्रिप्ट load :

ghci> :load helloworld

:reload (या :r ) ghci में सब कुछ पुनः लोड करता है:

Prelude> :l helloworld.hs 
[1 of 1] Compiling Main             ( helloworld.hs, interpreted )

<some time later after some edits>

*Main> :r
Ok, modules loaded: Main.

स्पष्टीकरण:

यह पहली पंक्ति एक प्रकार का हस्ताक्षर है, जो main के प्रकार की घोषणा करता है:

main :: IO ()

प्रकार के मान IO () उन कार्यों का वर्णन करते हैं जो बाहरी दुनिया के साथ बातचीत कर सकते हैं।

क्योंकि हास्केल में एक पूरी तरह से हिंडले-मिलनर प्रकार की प्रणाली है जो स्वचालित प्रकार की खोज के लिए अनुमति देती है, प्रकार के हस्ताक्षर तकनीकी रूप से वैकल्पिक हैं: यदि आप main :: IO () से main :: IO () छोड़ देते हैं main :: IO () , संकलक प्रकार का अनुमान लगाने में सक्षम हो जाएगा main की परिभाषा का विश्लेषण। हालांकि, यह बहुत ही खराब माना जाता है कि शीर्ष स्तर की परिभाषाओं के लिए टाइप हस्ताक्षर नहीं लिखना चाहिए। कारणों में शामिल हैं:

  • हास्केल में टाइप सिग्नेचर एक बहुत ही मददगार डॉक्यूमेंटेशन है क्योंकि टाइप सिस्टम इतना एक्सप्रेसिव है कि आप अक्सर देख सकते हैं कि किस तरह का फंक्शन सिर्फ उसके टाइप को देखकर अच्छा लगता है। यह "प्रलेखन" आसानी से GHCi जैसे उपकरणों के साथ पहुँचा जा सकता है। और सामान्य प्रलेखन के विपरीत, संकलक का प्रकार परीक्षक सुनिश्चित करेगा कि यह वास्तव में फ़ंक्शन की परिभाषा से मेल खाता है!

  • प्रकार के हस्ताक्षर बग को स्थानीय रखते हैं । यदि आप अपने प्रकार के हस्ताक्षर प्रदान किए बिना एक परिभाषा में गलती करते हैं, तो कंपाइलर तुरंत एक त्रुटि की रिपोर्ट नहीं कर सकता है, बल्कि इसके लिए बस एक निरर्थक प्रकार का अनुमान लगाता है, जिसके साथ यह वास्तव में टाइपकास्ट करता है। तब आपको उस मूल्य का उपयोग करते समय एक गुप्त त्रुटि संदेश मिल सकता है। एक हस्ताक्षर के साथ, संकलक उन जगहों पर स्पॉटिंग में बहुत अच्छा है जहां वे होते हैं।

यह दूसरी पंक्ति वास्तविक कार्य करती है:

main = putStrLn "Hello, World!"

यदि आप एक अनिवार्य भाषा से आते हैं, तो यह नोट करना मददगार हो सकता है कि यह परिभाषा इस प्रकार भी लिखी जा सकती है:

main = do {
   putStrLn "Hello, World!" ;
   return ()
   }

या समतुल्य (हास्केल में लेआउट-आधारित पार्सिंग है; लेकिन टैब और रिक्त स्थान को मिलाकर विसंगति करने से सावधान रहें जो इस तंत्र को भ्रमित करेगा):

main = do
    putStrLn "Hello, World!"
    return ()

do में प्रत्येक पंक्ति कुछ monadic (यहाँ, I / O) संगणना का प्रतिनिधित्व करती है, ताकि पूरे do block में दिए गए monad के लिए विशिष्ट तरीके से संयोजन करके इन उप-चरणों से युक्त समग्र क्रिया का प्रतिनिधित्व करता है (I / O के लिए) इसका मतलब है कि बस उन्हें एक के बाद एक निष्पादित करना)।

do सिंटैक्स अपने आप में मोनाड्स के लिए एक सिन्थेटिक शुगर है, जैसे कि IO , और return बिना किसी साइड इफ़ेक्ट या अतिरिक्त कम्प्यूटेशंस के बिना अपने तर्क का उत्पादन करने वाली एक नो-ऑप क्रिया है जो एक विशेष मोनड परिभाषा का हिस्सा हो सकता है।

उपरोक्त main = putStrLn "Hello, World!" को परिभाषित करने के समान है main = putStrLn "Hello, World!" , क्योंकि मूल्य putStrLn "Hello, World!" पहले से ही प्रकार IO () । एक "बयान" के रूप में देखा, putStrLn "Hello, World!" एक संपूर्ण कार्यक्रम के रूप में देखा जा सकता है, और आप इस कार्यक्रम को संदर्भित करने के लिए main से परिभाषित करते हैं।

आप ऑनलाइन putStrLn के हस्ताक्षर putStrLn सकते हैं :

putStrLn :: String -> IO ()
-- thus,
putStrLn (v :: String) :: IO ()

putStrLn एक फ़ंक्शन है जो एक स्ट्रिंग को अपने तर्क के रूप में लेता है और I / O-कार्रवाई (यानी एक प्रोग्राम का प्रतिनिधित्व करने वाला एक मान जो रनटाइम निष्पादित कर सकता है) को आउटपुट करता है। रनटाइम हमेशा main नाम की कार्रवाई को निष्पादित करता है, इसलिए हमें बस इसे putStrLn "Hello, World!" समान putStrLn "Hello, World!" रूप में परिभाषित करना होगा putStrLn "Hello, World!"

कारख़ाने का

भाज्य समारोह एक हास्केल है "हैलो वर्ल्ड!" (और सामान्य रूप से कार्यात्मक प्रोग्रामिंग के लिए) इस अर्थ में कि यह भाषा के बुनियादी सिद्धांतों को सफलतापूर्वक प्रदर्शित करता है।

भिन्नता १

fac :: (Integral a) => a -> a
fac n = product [1..n]

लाइव डेमो

  • Integral अभिन्न संख्या प्रकारों का वर्ग है। उदाहरण में Int और Integer
  • (Integral a) => प्रकार पर एक बाधा देता है a ने कहा कि कक्षा में होना करने के लिए
  • fac :: a -> a कहना है कि fac एक फ़ंक्शन है जो a लेता a और a को लौटाता a
  • product एक ऐसा कार्य है जो सूची में सभी संख्याओं को एक साथ गुणा करके जमा करता है।
  • [1..n] विशेष संकेतन है जो enumFromTo 1 n ओर enumFromTo 1 n , और संख्या 1 ≤ x ≤ n numbers 1 ≤ x ≤ n1 ≤ x ≤ n

भिन्नता २

fac :: (Integral a) => a -> a
fac 0 = 1
fac n = n * fac (n - 1)

लाइव डेमो

यह भिन्नता फ़ंक्शन मिलान को अलग-अलग मामलों में विभाजित करने के लिए पैटर्न मिलान का उपयोग करती है। यदि तर्क 0 (तो कभी-कभी स्टॉप कंडीशन कहा जाता है) और दूसरी परिभाषा अन्यथा (परिभाषाओं का क्रम महत्वपूर्ण है) यदि पहली परिभाषा लागू की जाती है। यह भी प्रत्यावर्तन एक मिसाल के रूप में fac ही को दर्शाता है।


ऐसा नहीं है कि ध्यान देने योग्य है, नियमों को फिर से लिखने के कारण, के दोनों संस्करणों fac समान मशीन कोड के लिए जब सक्रिय अनुकूलन के साथ GHC का उपयोग कर संकलित कर देगा। इसलिए, दक्षता के मामले में दोनों समान होंगे।

फाइबोनैचि, आलसी मूल्यांकन का उपयोग करना

आलसी मूल्यांकन का मतलब हैस्केल केवल उन सूची वस्तुओं का मूल्यांकन करेगा जिनके मूल्यों की आवश्यकता है।

मूल पुनरावर्ती परिभाषा है:

f (0)  <-  0
f (1)  <-  1
f (n)  <-  f (n-1) + f (n-2)

यदि सीधे मूल्यांकन किया जाए, तो यह बहुत धीमी गति से होगा। लेकिन, कल्पना कीजिए कि हमारे पास एक सूची है जो सभी परिणामों को रिकॉर्ड करती है,

fibs !! n  <-  f (n) 

फिर

                  ┌──────┐   ┌──────┐   ┌──────┐
                  │ f(0) │   │ f(1) │   │ f(2) │
fibs  ->  0 : 1 : │  +   │ : │  +   │ : │  +   │ :  .....
                  │ f(1) │   │ f(2) │   │ f(3) │
                  └──────┘   └──────┘   └──────┘

                  ┌────────────────────────────────────────┐
                  │ f(0)   :   f(1)   :   f(2)   :  .....  │ 
                  └────────────────────────────────────────┘
      ->  0 : 1 :               +
                  ┌────────────────────────────────────────┐
                  │ f(1)   :   f(2)   :   f(3)   :  .....  │
                  └────────────────────────────────────────┘

इसे इस प्रकार कोडित किया गया है:

fibn n = fibs !! n
    where
    fibs = 0 : 1 : map f [2..]
    f n = fibs !! (n-1) + fibs !! (n-2)

या भी

GHCi> let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
GHCi> take 10 fibs
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

zipWith दी गई दो सूचियों के संबंधित तत्वों को दिए गए बाइनरी फ़ंक्शन को लागू करके एक सूची बनाता है, इसलिए zipWith (+) [x1, x2, ...] [y1, y2, ...] [x1 + y1, x2 + y2, ...] बराबर है [x1 + y1, x2 + y2, ...]

लेखन का एक अन्य तरीका fibs साथ है scanl समारोह :

GHCi> let fibs = 0 : scanl (+) 1 fibs
GHCi> take 10 fibs
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

scanl उन आंशिक परिणामों की सूची बनाता है जो कि इनपुट सूची के साथ बाएं से दाएं की ओर काम करते हुए, foldl उत्पन्न होते हैं। यही है, scanl f z0 [x1, x2, ...] [z0, z1, z2, ...] where z1 = f z0 x1; z2 = f z1 x2; ... बराबर है [z0, z1, z2, ...] where z1 = f z0 x1; z2 = f z1 x2; ...

आलसी मूल्यांकन के लिए धन्यवाद, दोनों फ़ंक्शन पूरी तरह से कंप्यूटिंग के बिना अनंत सूचियों को परिभाषित करते हैं। यही है, हम एक fib फ़ंक्शन लिख सकते हैं, जो कि निर्बाध फाइबोनैचि अनुक्रम के nth तत्व को प्राप्त करता है:

GHCi> let fib n = fibs !! n  -- (!!) being the list subscript operator
-- or in point-free style:
GHCi> let fib = (fibs !!)
GHCi> fib 9
34

शुरू करना

ऑनलाइन REPL

हास्केल लिखना शुरू करने का सबसे आसान तरीका शायद हास्केल वेबसाइट या ट्राई हास्केल पर जाकर होम पेज पर ऑनलाइन आरईपीएल (रीड-इवल-प्रिंट-लूप) का उपयोग करना है। ऑनलाइन REPL सबसे बुनियादी कार्यक्षमता और यहां तक कि कुछ IO का समर्थन करता है। एक बुनियादी ट्यूटोरियल भी उपलब्ध है जिसे कमांड help टाइप करके शुरू किया जा सकता है। हास्केल की मूल बातें सीखना शुरू करने और कुछ सामानों को आज़माने के लिए एक आदर्श उपकरण।

GHC (i)

प्रोग्रामर जो थोड़ा और अधिक संलग्न करने के लिए तैयार हैं, उनके लिए GHCi , एक इंटरैक्टिव वातावरण है जो ग्लोरियस / ग्लासगो हास्केल कंपाइलर के साथ आता है। जीएचसी को अलग से स्थापित किया जा सकता है, लेकिन यह केवल एक संकलक है। नए पुस्तकालयों को स्थापित करने में सक्षम होने के लिए, कैबल और स्टैक जैसे उपकरणों को भी स्थापित किया जाना चाहिए। यदि आप एक यूनिक्स जैसी ऑपरेटिंग सिस्टम चला रहे हैं, तो सबसे आसान इंस्टॉलेशन स्टैक का उपयोग करके इंस्टॉल करना है:

curl -sSL https://get.haskellstack.org/ | sh

यह आपके सिस्टम के बाकी हिस्सों से पृथक जीएचसी को स्थापित करता है, इसलिए इसे निकालना आसान है। हालांकि सभी कमांड्स को stack से पहले होना चाहिए। एक अन्य सरल तरीका हैस्केल प्लेटफॉर्म को स्थापित करना। मंच दो स्वादों में मौजूद है:

  1. न्यूनतम वितरण में केवल GHC (संकलन करने के लिए) और Cabal / Stack (संकुल को स्थापित करने और बनाने के लिए) शामिल है
  2. पूर्ण वितरण में अतिरिक्त रूप से परियोजना विकास, रूपरेखा और कवरेज विश्लेषण के उपकरण शामिल हैं। इसके अलावा व्यापक रूप से उपयोग किए जाने वाले पैकेजों का एक अतिरिक्त सेट शामिल है।

इन प्लेटफार्मों को इंस्टॉलर डाउनलोड करके और निर्देशों का पालन करके या अपने वितरण के पैकेज मैनेजर का उपयोग करके स्थापित किया जा सकता है (ध्यान दें कि यह संस्करण अप-टू-डेट होने की गारंटी नहीं है):

  • उबंटू, डेबियन, मिंट:

    sudo apt-get install haskell-platform
    
  • फेडोरा:

    sudo dnf install haskell-platform
    
  • लाल टोपी:

    sudo yum install haskell-platform
    
  • आर्क लिनक्स:

    sudo pacman -S ghc cabal-install haskell-haddock-api \
                   haskell-haddock-library happy alex
    
  • Gentoo:

    sudo layman -a haskell
    sudo emerge haskell-platform
    
  • होमब्रे के साथ OSX:

    brew cask install haskell-platform
    
  • MacXorts के साथ OSX:

    sudo port install haskell-platform
    

एक बार स्थापित होने के बाद, टर्मिनल में कहीं भी ghci कमांड को लागू करके GHCi को शुरू करना संभव है। यदि स्थापना अच्छी तरह से चली गई, तो कंसोल को कुछ ऐसा दिखना चाहिए

me@notebook:~$ ghci
GHCi, version 6.12.1: http://www.haskell.org/ghc/  :? for help
Prelude> 

संभवतः लाइब्रेरी के बारे में कुछ और जानकारी के साथ Prelude> से पहले लोड किया गया है। अब, कंसोल एक Haskell REPL बन गया है और आप ऑनलाइन REPL के साथ Haskell कोड निष्पादित कर सकते हैं। इस संवादात्मक वातावरण को छोड़ने के लिए, कोई व्यक्ति टाइप कर सकता है :q या :quitGHCi में कौन से कमांड उपलब्ध हैं, इस बारे में अधिक जानकारी के लिए :? जैसा कि शुरुआती स्क्रीन में संकेत दिया गया है।

क्योंकि एक ही लाइन पर बार-बार एक ही चीजें लिखना हमेशा व्यावहारिक रूप से नहीं होता है, हो सकता है कि फाइलों में हास्केल कोड लिखना एक अच्छा विचार हो। इन फ़ाइलों को सामान्य रूप से है .hs एक विस्तार के लिए और का उपयोग करके आरईपीएल में लोड किया जा सकता है :l या :load

जैसा कि पहले उल्लेख किया गया है, GHCi GHC का एक हिस्सा है, जो वास्तव में एक संकलक है। इस संकलक का उपयोग एक। .hs फाइल कोड के साथ एक चल कार्यक्रम में बदलने के लिए किया जा सकता है। क्योंकि .hs फ़ाइल में बहुत सारे फ़ंक्शन हो सकते हैं, फ़ाइल में एक main फ़ंक्शन को परिभाषित किया जाना चाहिए। यह कार्यक्रम के लिए शुरुआती बिंदु होगा। फ़ाइल test.hs कमांड के साथ संकलित किया जा सकता है

ghc test.hs

यदि कोई त्रुटि नहीं थी और main फ़ंक्शन सही ढंग से परिभाषित किया गया था, तो यह ऑब्जेक्ट फ़ाइलें और एक निष्पादन योग्य बना देगा।

अधिक उन्नत उपकरण

  1. यह पैकेज प्रबंधक के रूप में पहले ही उल्लेख किया जा चुका है, लेकिन स्टैक पूरी तरह से अलग-अलग तरीकों से हास्केल विकास के लिए एक उपयोगी उपकरण हो सकता है। एक बार स्थापित होने के बाद, यह सक्षम है

    • स्थापित करने ( जीएचसी के कई संस्करण)
    • परियोजना निर्माण और मचान
    • निर्भरता प्रबंधन
    • निर्माण और परीक्षण परियोजनाएं
    • बेंच मार्किंग
  2. IHaskell IPython के लिए एक हैस्केल कर्नेल है और मार्कडाउन और गणितीय राशन के साथ (रननेबल) कोड को संयोजित करने की अनुमति देता है।

अभाज्य

कुछ सबसे प्रमुख संस्करण:

100 से नीचे

import Data.List ( (\\) )

ps100 = ((([2..100] \\ [4,6..100]) \\ [6,9..100]) \\ [10,15..100]) \\ [14,21..100]

   -- = (((2:[3,5..100]) \\ [9,15..100]) \\ [25,35..100]) \\ [49,63..100]

   -- = (2:[3,5..100]) \\ ([9,15..100] ++ [25,35..100] ++ [49,63..100])

असीमित

डेटा-ऑर्डलिस्ट पैकेज का उपयोग करके एराटोस्थनीज की छलनी:

import qualified Data.List.Ordered

ps   = 2 : _Y ((3:) . minus [5,7..] . unionAll . map (\p -> [p*p, p*p+2*p..]))

_Y g = g (_Y g)   -- = g (g (_Y g)) = g (g (g (g (...)))) = g . g . g . g . ...

परंपरागत

(एक उप-इष्टतम परीक्षण प्रभाग छलनी)

ps = sieve [2..]
     where
     sieve (x:xs) = [x] ++ sieve [y | y <- xs, rem y x > 0]

-- = map head ( iterate (\(x:xs) -> filter ((> 0).(`rem` x)) xs) [2..] )

इष्टतम परीक्षण प्रभाग

ps = 2 : [n | n <- [3..], all ((> 0).rem n) $ takeWhile ((<= n).(^2)) ps]

-- = 2 : [n | n <- [3..], foldr (\p r-> p*p > n || (rem n p > 0 && r)) True ps]

संक्रमणकालीन

परीक्षण प्रभाग से एराटोस्थनीज की छलनी:

[n | n <- [2..], []==[i | i <- [2..n-1], j <- [0,i..n], j==n]]

सबसे छोटा कोड

nubBy (((>1).).gcd) [2..]          -- i.e., nubBy (\a b -> gcd a b > 1) [2..]

nubBy भी है से Data.List , जैसे (\\)

घोषित मूल्य

हम इस तरह से REPL में अभिव्यक्ति की एक श्रृंखला की घोषणा कर सकते हैं:

Prelude> let x = 5
Prelude> let y = 2 * 5 + x
Prelude> let result = y * 10
Prelude> x
5
Prelude> y
15
Prelude> result
150

एक फ़ाइल में समान मान घोषित करने के लिए हम निम्नलिखित लिखते हैं:

-- demo.hs

module Demo where
-- We declare the name of our module so 
-- it can be imported by name in a project.

x = 5

y = 2 * 5 + x

result = y * 10

चर नामों के विपरीत, मॉड्यूल नामों को कैपिटल में रखा जाता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow