এলমে, আমি 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
অন্যরকম সমস্যার সমাধান হয়। যদি আপনি ওওপি থেকে আসেন, তবে উত্তরাধিকার, অপারেটর ওভারলোডিং ইত্যাদির সাহায্যে আপনি সমস্যাটি সমাধান করেন -
পোস্ট সিস্টেমের মতো বার্তাগুলি অতিক্রম করার সময় এটি ঘটে এমন একটি সাধারণ জায়গা। আপনি যখন কোনও চিঠি প্রেরণ করেন, আপনি ডাক সিস্টেমটি সমস্ত বার্তাকে একই জিনিস হিসাবে দেখাতে চান, সুতরাং আপনাকে কেবলমাত্র ডাক সিস্টেম একবার ডিজাইন করতে হবে। এবং তদ্ব্যতীত, বার্তাটি রাউটিংয়ের কাজটি অন্তর্ভুক্ত থাকা বার্তার থেকে স্বতন্ত্র হওয়া উচিত। কেবলমাত্র যখন চিঠিটি তার গন্তব্যস্থলে পৌঁছেছে আপনি কী বার্তাটি কী তা যত্নবান হন।
একইভাবে, আমরা type
ঘটতে পারে এমন বিভিন্ন ধরণের বার্তাগুলির একটি ইউনিয়ন হিসাবে সংজ্ঞায়িত করতে পারি । বলুন আমরা কলেজের শিক্ষার্থীদের মধ্যে তাদের পিতামাতার কাছে একটি বার্তা ব্যবস্থা প্রয়োগ করছি। তাই কলেজের বাচ্চারা কেবল দুটি বার্তা পাঠাতে পারে: 'আমার বিয়ারের অর্থ দরকার' এবং 'আমার অন্তর্বাস প্রয়োজন'।
type MessageHome = NeedBeerMoney | NeedUnderpants
সুতরাং এখন, যখন আমরা রাউটিং সিস্টেমটি ডিজাইন করি, তখন আমাদের ফাংশনগুলির MessageHome
ধরণগুলি বিভিন্ন ধরণের বার্তাগুলি যেভাবে হতে পারে তা নিয়ে চিন্তা করার পরিবর্তে কেবল তার বাইরে চলে যেতে পারে। রাউটিং সিস্টেমের কোনও যত্ন নেই। এটা শুধুমাত্র একটি জানি দরকার MessageHome
। এটি কেবল তখনই বার্তাটি তার গন্তব্য, পিতামাতার বাড়িতে পৌঁছে যায় যে এটি কী তা আপনাকে খুঁজে বের করতে হবে।
case message of
NeedBeerMoney ->
sayNo()
NeedUnderpants ->
sendUnderpants(3)
আপনি যদি এলম আর্কিটেকচারটি জানেন, আপডেট ফাংশনটি একটি দৈত্য কেস স্টেটমেন্ট because এবং বার্তাটি পাস করার সময় আমরা একক প্রকারের জন্য ইউনিয়ন প্রকারগুলি ব্যবহার করি তবে এটি কী বার্তাটি ছিল তা ঠিক তাড়িত করার জন্য কেস স্টেটমেন্ট ব্যবহার করতে পারি, সুতরাং আমরা এটির সাথে ডিল করতে পারি।
আমি ব্যবহারের ক্ষেত্রে ফোকাস করে এবং কনস্ট্রাক্টর ফাংশন এবং মডিউলগুলির জন্য একটি সামান্য প্রসঙ্গ সরবরাহ করে পূর্ববর্তী উত্তরগুলির পরিপূরক করি।
type alias
একটি রেকর্ডের জন্য একটি নাম এবং একটি কনস্ট্রাক্টর ফাংশন তৈরি করুন
এটি সর্বাধিক সাধারণ ব্যবহারের ক্ষেত্রে: আপনি কোনও নির্দিষ্ট রেকর্ড বিন্যাসের জন্য একটি বিকল্প নাম এবং কনস্ট্রাক্টর ফাংশনটি সংজ্ঞায়িত করতে পারেন।
type alias Person =
{ name : String
, age : Int
}
প্রকারের উপন্যাসটি সংজ্ঞায়িত করা হলে নিম্নলিখিত কন্সট্রাক্টর ফাংশনটি (সিউডো কোড) বোঝায়:
Person : String -> Int -> { name : String, age : Int }
উদাহরণস্বরূপ আপনি যখন জসন ডিকোডার লিখতে চান তখন এটি কার্যকর হতে পারে।
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
এলমিউরোপ ২০১ Ric-তে রিচার্ড ফিল্ডম্যানের আলাপ যখন এই স্টাইলটি ব্যবহারের পক্ষে উপযুক্ত তখন এ সম্পর্কে আরও কিছু অন্তর্দৃষ্টি দিতে পারে।
পুনরায় নামকরণ স্টাফ
আপনি এটি করতে পারেন, কারণ এই উদাহরণের মতো নতুন নামগুলি পরে আপনার কোডে অতিরিক্ত অর্থ প্রদান করতে পারে
type alias Id = String
type alias ElapsedTime = Time
type SessionStatus
= NotStarted
| Active Id ElapsedTime
| Finished Id
মূল ক্ষেত্রে ব্যবহারের এই ধরণেরTime
আরও ভাল উদাহরণ হ'ল ।
কোনও ভিন্ন মডিউল থেকে কোনও প্রকার পুনরায় প্রকাশ করা
যদি আপনি প্যাকেজ (কোনও অ্যাপ্লিকেশন নয়) লিখতে থাকেন তবে আপনাকে একটি মডিউলে একটি প্রকার প্রয়োগ করতে হবে, সম্ভবত কোনও অভ্যন্তরীণ (প্রকাশিত নয়) মডিউল থাকতে পারে, তবে আপনি এই প্রকারটি প্রকাশ করতে চান একটি পৃথক (সর্বজনীন) মডিউল। অথবা, বিকল্পভাবে, আপনি একাধিক মডিউল থেকে আপনার প্রকারটি প্রকাশ করতে চান।
Task
মূল এবং Http.Request এইচটিপি- র প্রথম উদাহরণ, অন্যদিকে Json.Encode.Value এবং Json.Decode.Value যুগলটি পরবর্তীকালের উদাহরণ the
আপনি কেবল তখনই এটি করতে পারেন যখন আপনি অন্যথায় ধরণের অস্বচ্ছ রাখতে চান: আপনি নির্মাণকারীর কার্যাদি প্রকাশ করবেন না। বিশদ জন্য 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
মডিউল একটি ব্যক্তি মান এবং শুধুমাত্র এটি কোডটি করতে প্যাটার্ন ম্যাচ তৈরি করতে পারেন।
মূল পার্থক্য, যেমনটি আমি এটি দেখতে পাচ্ছি, আপনি যদি "synomical" টাইপ ব্যবহার করেন তবে টাইপ চেকার আপনাকে চিৎকার করবে কিনা।
নিম্নলিখিত ফাইলটি তৈরি করুন, এটিকে কোথাও রেখে চালনা করুন 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
গলি হবে। সমাপ্তি:
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
, আপনি ছেলেরা জোশ ক্লেটন থেকে নিবন্ধটি উল্লেখ করতে পারেন