एल्म में, मैं समझ नहीं सकता type
कि उपयुक्त कीवर्ड बनाम कब है type alias
। दस्तावेज़ीकरण में इसकी व्याख्या नहीं है, और न ही मुझे जारी नोटों में कोई मिल सकता है। क्या यह कहीं दस्तावेज है?
जवाबों:
मैं इसे कैसे समझता हूं:
type
नए यूनियन प्रकारों को परिभाषित करने के लिए उपयोग किया जाता है:
type Thing = Something | SomethingElse
इस परिभाषा से पहले Something
और SomethingElse
कुछ भी मतलब नहीं था। अब वे दोनों प्रकार के हैं Thing
, जिन्हें हमने अभी परिभाषित किया है।
type alias
इसका उपयोग कुछ अन्य प्रकार के नाम देने के लिए किया जाता है जो पहले से मौजूद हैं:
type alias Location = { lat:Int, long:Int }
{ lat = 5, long = 10 }
प्रकार है { lat:Int, long:Int }
, जो पहले से ही एक वैध प्रकार था। लेकिन अब हम यह भी कह सकते हैं कि इसके प्रकार हैंLocation
क्योंकि यह उसी प्रकार के लिए एक उपनाम है।
यह ध्यान देने योग्य है कि निम्नलिखित केवल ठीक और प्रदर्शन को संकलित करेगा "thing"
। भले ही हम निर्दिष्ट करते हैं thing
कि एक है String
और एक aliasedStringIdentity
लेता है AliasedString
, हमें एक त्रुटि नहीं मिलेगी कि String
/ के बीच एक प्रकार का बेमेल है AliasedString
:
import Graphics.Element exposing (show)
type alias AliasedString = String
aliasedStringIdentity: AliasedString -> AliasedString
aliasedStringIdentity s = s
thing : String
thing = "thing"
main =
show <| aliasedStringIdentity thing
{ lat:Int, long:Int }
एक नए प्रकार को परिभाषित नहीं करता है। यह पहले से ही मान्य प्रकार है। type alias Location = { lat:Int, long:Int }
यह भी एक नए प्रकार को परिभाषित नहीं करता है, यह पहले से ही मान्य प्रकार को एक और (शायद अधिक वर्णनात्मक) नाम देता है। type Location = Geo { lat:Int, long:Int }
एक नए प्रकार को परिभाषित करेगा ( Location
)
कुंजी शब्द है alias
। प्रोग्रामिंग के दौरान, जब आप चीजों को एक साथ रखना चाहते हैं, तो आप इसे रिकॉर्ड में रखते हैं, जैसे कि एक बिंदु के मामले में
{ x = 5, y = 4 }
या एक छात्र रिकॉर्ड।
{ name = "Billy Bob", grade = 10, classof = 1998 }
अब, यदि आपको इन अभिलेखों को पास करने की आवश्यकता है, तो आपको पूरे प्रकार का विवरण देना होगा, जैसे:
add : { x:Int, y:Int } -> { x:Int, y:Int } -> { x:Int, y:Int }
add a b =
{ a.x + b.x, a.y + b.y }
यदि आप एक बिंदु को उर्फ कर सकते हैं, तो हस्ताक्षर लिखना बहुत आसान होगा!
type alias Point = { x:Int, y:Int }
add : Point -> Point -> Point
add a b =
{ a.x + b.x, a.y + b.y }
तो एक उपनाम किसी और चीज के लिए एक आशुलिपि है। यहाँ, यह एक रिकॉर्ड प्रकार के लिए एक आशुलिपि है। आप इसे एक रिकॉर्ड प्रकार को एक नाम देने के रूप में सोच सकते हैं जिसका आप अक्सर उपयोग कर रहे हैं। इसलिए इसे उपनाम कहा जाता है - यह नग्न रिकॉर्ड प्रकार के लिए एक और नाम है जिसका प्रतिनिधित्व किया जाता है{ x:Int, y:Int }
जबकि type
एक अलग समस्या हल करती है। यदि आप OOP से आ रहे हैं, तो यह वह समस्या है जिसे आप वंशानुक्रम, ऑपरेटर अधिभार आदि के साथ हल करते हैं ।-- कभी-कभी, आप डेटा को एक सामान्य चीज़ के रूप में व्यवहार करना चाहते हैं, और कभी-कभी आप इसे एक विशिष्ट चीज़ की तरह व्यवहार करना चाहते हैं।
संदेशों के आसपास से गुजरते समय एक आम बात यह है - डाक प्रणाली की तरह। जब आप एक पत्र भेजते हैं, तो आप चाहते हैं कि डाक प्रणाली सभी संदेशों को एक ही तरह से व्यवहार करे, इसलिए आपको केवल एक बार डाक प्रणाली को डिजाइन करना होगा। और इसके अलावा, संदेश को रूट करने का काम भीतर निहित संदेश से स्वतंत्र होना चाहिए। यह केवल तभी होता है जब पत्र अपने गंतव्य तक पहुंचता है, क्या आप इस बात की परवाह करते हैं कि संदेश क्या है।
उसी तरह, हम type
उन सभी विभिन्न प्रकार के संदेशों के एक संघ के रूप में परिभाषित कर सकते हैं जो हो सकते हैं। कहते हैं कि हम कॉलेज के छात्रों के बीच उनके अभिभावकों के लिए एक संदेश प्रणाली लागू कर रहे हैं। इसलिए केवल दो संदेश हैं कॉलेज के बच्चे भेज सकते हैं: 'मुझे बीयर के पैसे चाहिए' और 'मुझे अंडरपेंट चाहिए'।
type MessageHome = NeedBeerMoney | NeedUnderpants
इसलिए अब, जब हम राउटिंग सिस्टम को डिज़ाइन करते हैं, तो हमारे कार्यों के प्रकार केवल चारों ओर से गुजर सकते हैं MessageHome
, इसके बजाय यह हो सकता है कि सभी विभिन्न प्रकार के संदेशों के बारे में चिंता न करें। रूटिंग सिस्टम परवाह नहीं करता है। यह केवल जानना आवश्यक है कि यह एक है MessageHome
। यह तभी होता है जब संदेश अपने गंतव्य, माता-पिता के घर तक पहुंचता है, आपको यह पता लगाने की आवश्यकता है कि यह क्या है।
case message of
NeedBeerMoney ->
sayNo()
NeedUnderpants ->
sendUnderpants(3)
यदि आप एल्म आर्किटेक्चर को जानते हैं, तो अपडेट फ़ंक्शन एक विशाल केस स्टेटमेंट है, क्योंकि यह वह स्थान है जहां संदेश रूट हो जाता है, और इसलिए संसाधित किया जाता है। और हम मैसेज पास करते समय डील करने के लिए यूनियन टाइप का उपयोग करते हैं, लेकिन फिर केस स्टेटमेंट का उपयोग करके यह बता सकते हैं कि यह क्या संदेश था, इसलिए हम इससे निपट सकते हैं।
मुझे उपयोग-मामलों पर ध्यान केंद्रित करके और निर्माण कार्यों और मॉड्यूल पर थोड़ा संदर्भ प्रदान करके पिछले उत्तरों को पूरक करने दें।
type alias
एक रिकॉर्ड के लिए एक उपनाम और एक निर्माता फ़ंक्शन बनाएं
यह सबसे आम उपयोग-मामला है: आप एक विशेष प्रकार के रिकॉर्ड प्रारूप के लिए एक वैकल्पिक नाम और निर्माता फ़ंक्शन को परिभाषित कर सकते हैं।
type alias Person =
{ name : String
, age : Int
}
प्रकार को अन्य नाम से परिभाषित करना स्वचालित रूप से निम्नलिखित रचनाकार फ़ंक्शन (छद्म कोड) का अर्थ है:
Person : String -> Int -> { name : String, age : Int }
यह आसान हो सकता है, उदाहरण के लिए जब आप एक Json डिकोडर लिखना चाहते हैं।
personDecoder : Json.Decode.Decoder Person
personDecoder =
Json.Decode.map2 Person
(Json.Decode.field "name" Json.Decode.String)
(Json.Decode.field "age" Int)
आवश्यक फ़ील्ड निर्दिष्ट करें
वे कभी-कभी इसे "एक्स्टेंसिबल रिकॉर्ड" कहते हैं, जो भ्रामक हो सकता है। इस सिंटैक्स का उपयोग यह निर्दिष्ट करने के लिए किया जा सकता है कि आप विशेष क्षेत्र के साथ कुछ रिकॉर्ड की उम्मीद कर रहे हैं। जैसे कि:
type alias NamedThing x =
{ x
| name : String
}
showName : NamedThing x -> Html msg
showName thing =
Html.text thing.name
फिर आप इस तरह के उपरोक्त फ़ंक्शन का उपयोग कर सकते हैं (उदाहरण के लिए आपके विचार में):
let
joe = { name = "Joe", age = 34 }
in
showName joe
ElmEurope 2017 पर रिचर्ड फेल्डमैन की बात इस शैली का उपयोग करने के लिए कुछ और जानकारी प्रदान कर सकती है।
सामान का नाम बदलना
आप ऐसा कर सकते हैं, क्योंकि नए नाम आपके कोड में बाद में इस उदाहरण की तरह अतिरिक्त अर्थ प्रदान कर सकते हैं
type alias Id = String
type alias ElapsedTime = Time
type SessionStatus
= NotStarted
| Active Id ElapsedTime
| Finished Id
कोर में इस तरह के उपयोगTime
का शायद एक बेहतर उदाहरण है ।
एक अलग मॉड्यूल से एक प्रकार को फिर से उजागर करना
यदि आप एक पैकेज लिख रहे हैं (एक आवेदन नहीं), तो आपको एक मॉड्यूल में एक प्रकार लागू करने की आवश्यकता हो सकती है, शायद एक आंतरिक (उजागर नहीं) मॉड्यूल में, लेकिन आप प्रकार को उजागर करना चाहते हैं एक अलग (सार्वजनिक) मॉड्यूल। या, वैकल्पिक रूप से, आप अपने प्रकार को कई मॉड्यूल से उजागर करना चाहते हैं।
Task
कोर में और Http.Request में Http पहली बार के लिए उदाहरण हैं, जबकि Json.Encode.Value और Json.Decode.Value जोड़ी बाद का एक उदाहरण है।
आप इसे केवल तभी कर सकते हैं जब आप अन्यथा प्रकार अपारदर्शी रखना चाहते हैं: आप निर्माण कार्यों को उजागर नहीं करते हैं। जानकारी के लिए type
नीचे के उपयोग देखें।
यह ध्यान देने योग्य है कि उपरोक्त उदाहरणों में केवल # 1 एक कंस्ट्रक्टर फ़ंक्शन प्रदान करता है। यदि आप # 1 में अपने प्रकार के उपनाम module Data exposing (Person)
को उजागर करते हैं, तो यह प्रकार नाम के साथ-साथ निर्माण कार्य को भी उजागर करेगा।
type
टैग किए गए यूनियन प्रकार को परिभाषित करें
यह सबसे आम उपयोग-मामला है, इसका एक अच्छा उदाहरण Maybe
कोर में प्रकार है :
type Maybe a
= Just a
| Nothing
जब आप एक प्रकार को परिभाषित करते हैं, तो आप इसके निर्माण कार्यों को भी परिभाषित करते हैं। शायद के मामले में ये (छद्म कोड) हैं:
Just : a -> Maybe a
Nothing : Maybe a
जिसका अर्थ है कि यदि आप इस मूल्य की घोषणा करते हैं:
mayHaveANumber : Maybe Int
आप इसे या तो बना सकते हैं
mayHaveANumber = Nothing
या
mayHaveANumber = Just 5
Just
और Nothing
टैग न केवल निर्माता कार्यों के रूप में सेवा, वे भी विनाशकर्ता या एक में पैटर्न के रूप में सेवा case
अभिव्यक्ति। जिसका अर्थ है कि इन पैटर्नों का उपयोग करके आप अंदर देख सकते हैं Maybe
:
showValue : Maybe Int -> Html msg
showValue mayHaveANumber =
case mayHaveANumber of
Nothing ->
Html.text "N/A"
Just number ->
Html.text (toString number)
आप ऐसा कर सकते हैं, क्योंकि शायद मॉड्यूल को परिभाषित किया गया है
module Maybe exposing
( Maybe(Just,Nothing)
यह भी कह सकता था
module Maybe exposing
( Maybe(..)
इस मामले में दो बराबर हैं, लेकिन स्पष्ट रूप से एल्म में एक गुण माना जाता है, खासकर जब आप पैकेज लिख रहे हों।
कार्यान्वयन विवरण को छिपाना
जैसा कि ऊपर बताया गया है कि यह एक जानबूझकर पसंद है कि Maybe
अन्य मॉड्यूल के लिए निर्माण कार्य दिखाई देते हैं।
हालांकि, अन्य मामले भी हैं, जब लेखक उन्हें छिपाने का फैसला करता है। कोर में इसका एक उदाहरण हैDict
। पैकेज के उपभोक्ता के रूप में, आपको Dict
सीधे नोड्स के साथ पीछे और गड़बड़ करने वाले लाल / काले पेड़ के एल्गोरिथ्म का कार्यान्वयन विवरण देखने में सक्षम नहीं होना चाहिए । कंस्ट्रक्टर फ़ंक्शंस को छुपाना आपके मॉड्यूल / पैकेज के उपभोक्ता को आपके द्वारा किए गए फ़ंक्शंस के माध्यम से केवल आपके प्रकार (और फिर उन मानों को बदलना) के मूल्यों को बनाने के लिए मजबूर करता है।
यही कारण है कि कभी-कभी इस तरह का सामान कोड में दिखाई देता है
type Person =
Person { name : String, age : Int }
type alias
इस पोस्ट के शीर्ष पर परिभाषा के विपरीत , यह सिंटैक्स केवल एक कंस्ट्रक्टर फ़ंक्शन के साथ एक नया "यूनियन" प्रकार बनाता है, लेकिन उस कंस्ट्रक्टर फ़ंक्शन को अन्य मॉड्यूल / पैकेज से छिपाया जा सकता है।
यदि प्रकार इस तरह से उजागर होता है:
module Data exposing (Person)
Data
मॉड्यूल में केवल कोड एक व्यक्ति मूल्य बना सकता है और केवल उस कोड को उस पर मिलान कर सकता है।
मुख्य अंतर, जैसा कि मैं इसे देखता हूं, यह है कि क्या टाइप चेकर आप पर चिल्लाएगा यदि आप "सिनोमिकल" प्रकार का उपयोग करते हैं।
निम्नलिखित फ़ाइल बनाएं, इसे कहीं रखें और चलाएं elm-reactor
, फिर http://localhost:8000
अंतर देखने के लिए जाएं:
-- Boilerplate code
module Main exposing (main)
import Html exposing (..)
main =
Html.beginnerProgram
{
model = identity,
view = view,
update = identity
}
-- Our type system
type alias IntRecordAlias = {x : Int}
type IntRecordType =
IntRecordType {x : Int}
inc : {x : Int} -> {x : Int}
inc r = {r | x = .x r + 1}
view model =
let
-- 1. This will work
r : IntRecordAlias
r = {x = 1}
-- 2. However, this won't work
-- r : IntRecordType
-- r = IntRecordType {x = 1}
in
Html.text <| toString <| inc r
यदि आप असहजता 2.
और टिप्पणी करते हैं 1.
तो आप देखेंगे:
The argument to function `inc` is causing a mismatch.
34| inc r
^
Function `inc` is expecting the argument to be:
{ x : Int }
But it is:
IntRecordType
एक alias
बस कुछ अन्य प्रकार, समान के लिए एक छोटा नाम है class
OOP में। समाप्ति:
type alias Point =
{ x : Int
, y : Int
}
एक type
तो आप की तरह प्रकार परिभाषित कर सकते हैं (उर्फ) के बिना, आप अपने खुद के प्रकार को परिभाषित करने देगा Int
, String
अनुप्रयोग, ... आप के लिए। उदाहरण के लिए, सामान्य स्थिति में, यह एप्लिकेशन की स्थिति का वर्णन करने के लिए उपयोग कर सकता है:
type AppState =
Loading --loading state
|Loaded --load successful
|Error String --Loading error
तो आप इसे view
एल्म में संभालना आसान कर सकते हैं :
-- VIEW
...
case appState of
Loading -> showSpinner
Loaded -> showSuccessData
Error error -> showError
...
मुझे लगता है कि आप type
और के बीच का अंतर जानते हैंtype alias
।
लेकिन क्यों और कैसे उपयोग करें type
और ऐप के type alias
साथ महत्वपूर्ण है elm
, आप लोग जोश क्लेटन के लेख का संदर्भ ले सकते हैं