Variant turi - Option type

Yilda dasturlash tillari (ko'proq) funktsional dasturlash tillar) va tip nazariyasi, an variant turi yoki balki yozing a polimorfik tip bu ixtiyoriy qiymatning kapsulasini ifodalaydi; masalan, ular qo'llanilganda mazmunli qiymatni qaytarishi yoki keltirmasligi mumkin bo'lgan funktsiyalarni qaytarish turi sifatida ishlatiladi. U bo'sh bo'lgan konstruktordan iborat (ko'pincha nomlanadi) Yo'q yoki Hech narsa yo'q) yoki asl ma'lumot turini o'z ichiga olgan A (ko'pincha yoziladi Faqat A yoki Ba'zi A).

Funktsional dasturlashdan tashqari alohida, ammo shunga o'xshash tushuncha ob'ektga yo'naltirilgan dasturlash, deyiladi bekor qilinadigan turlari (ko'pincha sifatida ifodalanadi A?). Variant turlari va bekor qilinadigan turlarning asosiy farqi shundaki, variant turlari uyalashni qo'llab-quvvatlaydi (Balki (Balki A)Ehtimol A), bo'sh turlar esa (String ?? = String?).

Nazariy jihatlar

Yilda tip nazariyasi, shunday yozilishi mumkin: . Bu berilgan qiymatlar to'plami uchun , parametr turi uchun to'g'ri qiymatlar to'plamiga to'liq bitta qo'shimcha qiymat (bo'sh qiymat) qo'shiladi . Bu dasturlashda tillarda mavjudligi bilan aks etadi belgilangan kasaba uyushmalari, variant turlarini kapsulali turdagi plus a-ning birlashtirilishi sifatida ifodalash mumkin birlik turi.[1]

In Kori-Xovard yozishmalari, variant turlari bilan bog'liq yo'q qilish to'g'risidagi qonun for uchun: x∨1 = 1.[Qanaqasiga? ]

Variant turini a sifatida ham ko'rish mumkin to'plam bitta yoki nol elementlardan iborat.[asl tadqiqotmi? ]

Variant turi ham a monad qaerda:[2]

qaytish = Faqat - Qiymatni ehtimolga aylantiradiHech narsa yo'q  >>= f = Hech narsa yo'q - Agar avvalgi monad bajarilmasa, ishlamay qoladi(Faqat x) >>= f = f x     - Ikkala monada ham muvaffaqiyatga erishganda muvaffaqiyatga erishadi

Variant turining monadik xususiyati xato va xatolarni samarali kuzatish uchun foydalidir.[3]

Ismlar va ta'riflar

Turli xil dasturlash tillarida variant turi har xil nom va ta'riflarga ega.

  • Yilda Agda, u nomlangan Balki variantlar bilan hech narsa va faqat a.
  • Yilda C ++ 17 u shablon sinfi sifatida aniqlanadi std::ixtiyoriy<T>, ixtiyoriy() bo'sh variantni yaratish uchun ishlatilishi mumkin. (Konstruktorlarning haddan tashqari yuklanishi tufayli monad qonunlarini buzishi mumkin.)
  • Yilda C #, deb belgilanadi Hech narsa yo'q<T> lekin odatda shunday yoziladi T?. (Monad qonunlarini buzadi.)
  • Yilda Coq, deb belgilanadi Induktiv variant (A:Turi) : Turi := | Biroz : A -> variant A | Yo'q : variant A..
  • Yilda Qarag'ay, u nomlangan Balkiva sifatida belgilanadi turi Balki a = Faqat a | Hech narsa yo'q.[4]
  • Yilda Xaskell, u nomlangan Balkiva sifatida belgilanadi ma'lumotlar Balki a = Hech narsa yo'q | Faqat a.
  • Yilda Idris, deb belgilanadi ma'lumotlar Balki a = Hech narsa yo'q | Faqat a.
  • Yilda Java, 8-versiyadan boshlab, u parametrlangan yakuniy sinf sifatida aniqlanadi Ixtiyoriy<T>. (Monad qonunlarini buzadi (xarita noto'g'ri bajarilgan).)
  • Yilda Yuliya, u nomlangan Hech narsa yo'q{T}. (Biroq, bu eskirgan.[5])
  • Yilda Kotlin, deb belgilanadi T?.[6] (Monad qonunlarini buzadi (uyalashni qo'llab-quvvatlamaydi).)
  • Yilda OCaml, deb belgilanadi turi 'a variant = Yo'q | Biroz ning 'a.
  • Yilda Perl 6, bu sukut bo'yicha, lekin siz qo'shishingiz mumkin :D. Variant bo'lmagan turga o'tish uchun "tabassum". (Monad qonunlarini buzadi (uyalashni qo'llab-quvvatlamaydi.))
  • Yilda Zang, deb belgilanadi enum Variant<T>{Yo'q,Biroz(T)}.
  • Yilda Scala, deb belgilanadi muhrlangan mavhum sinf Variant[+ A], kengaytirilgan tur final ish sinf Biroz[+ A](qiymat: A) va ish ob'ekt Yo'q.
  • Yilda Standart ML, deb belgilanadi ma'lumotlar turi 'a variant = Hech kim | BIROZ ning 'a.
  • Yilda Tez, deb belgilanadi enum Ixtiyoriy<T> { ish yo'q, biroz(T) } lekin odatda shunday yoziladi T?.[7]

Misollar

Ada

Ada variant turlarini bevosita amalga oshirmaydi, ammo yozuvni parametrlash uchun ishlatilishi mumkin bo'lgan kamsitilgan turlarini taqdim etadi. Option turini amalga oshirish uchun mantiqiy tip diskriminant sifatida ishlatiladi; Quyidagi misol har qanday cheklanmagan cheklangan turdan variant turini yaratish uchun umumiy ma'lumot beradi:

Umumiy  - har qanday cheklangan va cheklanmagan tur.  Turi Element_Type bu xususiy;Paket Ixtiyoriy_Type bu  - Diskriminant, Has_Element, haqiqat bo'lganda element maydoni mavjud,  - agar u noto'g'ri bo'lsa, maydonlar mavjud emas (shuning uchun null kalit so'z).  Turi Ixtiyoriy( Has_Element : Mantiqiy ) bu yozuv    ish Has_Element bu      qachon Yolg'on => Bekor;      qachon To'g'ri  => Element : Element_Type;    oxiri ish;  yakuniy yozuv;oxiri Ixtiyoriy_Type;

Scala

Scala asboblar Variant parametrlangan tur sifatida, shuning uchun o'zgaruvchi an bo'lishi mumkin Variant, quyidagi tarzda kirish mumkin:[8]

ob'ekt Asosiy {  // Ushbu funktsiya `Option`s 'ni dekonstruktsiya qilish uchun naqshga mos keladi  def hisoblash V1(tanlov: Variant[Int]): Ip =    tanlov o'yin {      ish Biroz(x) => s "Qiymat: $ x"      ish Yo'q    => "Qiymat yo'q"    }  // Ushbu funktsiya o'rnatilgan "katlama" usulidan foydalanadi  def hisoblash V2(tanlov: Variant[Int]): Ip =    tanlov.katlama("Qiymat yo'q")(x => s "Qiymat: $ x")  def asosiy(kamon: Array[Ip]): Birlik = {    // `Int` tipidagi` Option`s bo'lgan o'zgaruvchilarni aniqlang    val to'liq = Biroz(42)    val bo'sh: Variant[Int] = Yo'q    // computeV1 (to'liq) -> Qiymat: 42    println(s "computeV1 (to'liq) ->${hisoblash V1(to'liq)}")    // computeV1 (bo'sh) -> qiymat yo'q    println(s "computeV1 (bo'sh) ->${hisoblash V1(bo'sh)}")    // computeV2 (to'liq) -> Qiymat: 42    println(s "computeV2 (to'liq) ->${hisoblash V2(to'liq)}")    // computeV2 (bo'sh) -> qiymat yo'q    println(s "computeV2 (bo'sh) ->${hisoblash V2(bo'sh)}")  }}

Dan foydalanishning ikkita asosiy usuli Variant qiymat mavjud. Birinchisi, eng yaxshisi emas naqshlarni moslashtirish, birinchi misolda bo'lgani kabi. Ikkinchisi, eng yaxshi amaliyot - bu ikkinchi misolda bo'lgani kabi monadik yondashuv. Shu tarzda, dastur xavfsizdir, chunki u hech qanday istisno yoki xatoga yo'l qo'ymasligi mumkin (masalan, qiymatini olishga harakat qilib Variant ga teng bo'lgan o'zgaruvchi Yo'q). Shunday qilib, u aslida nol qiymatiga xavfsiz xavfsiz alternativ sifatida ishlaydi.

OCaml

OCaml asboblar Variant parametrlangan variant turi sifatida. Variantlar quyidagicha qurilgan va buzilgan:

(* Ushbu funktsiya `variant`s * dekonstruktsiya qilish uchun naqshga mos keladi.)ruxsat bering hisoblash_v1 = funktsiya  | Biroz x -> "Qiymat:" ^ string_of_int x  | Yo'q -> "Qiymat yo'q"(* Ushbu funktsiya o'rnatilgan "katlama" funktsiyasidan foydalanadi *)ruxsat bering hisoblash_v2 =  Variant.katlama ~yo'q:"Qiymat yo'q" ~biroz:(qiziqarli x -> "Qiymat:" ^ string_of_int x)ruxsat bering () =  (* "Int` * turidagi" variant "lar bo'lgan o'zgaruvchilarni aniqlang)  ruxsat bering to'liq = Biroz 42 yilda  ruxsat bering bo'sh = Yo'q yilda  (* compute_v1 to'liq -> qiymati: 42 *)  print_endline ("compute_v1 to'liq ->" ^ hisoblash_v1 to'liq);  (* compute_v1 bo'sh -> qiymat yo'q *)  print_endline ("compute_v1 empty ->" ^ hisoblash_v1 bo'sh);  (* compute_v2 to'liq -> qiymati: 42 *)  print_endline ("compute_v2 to'liq ->" ^ hisoblash_v2 to'liq);  (* compute_v2 bo'sh -> qiymat yo'q *)  print_endline ("compute_v2 empty ->" ^ hisoblash_v2 bo'sh)

F #

// Ushbu funktsiya `variant`s dekompozitsiyasi uchun naqshga mos keladiruxsat bering hisoblash_v1 = funktsiya    | Biroz x -> sprintf "Qiymat:% d" x    | Yo'q -> "Qiymat yo'q"// Ushbu funktsiya o'rnatilgan "katlama" funktsiyasidan foydalanadiruxsat bering hisoblash_v2 =    Variant.katlama (qiziqarli _ x -> sprintf "Qiymat:% d" x) "Qiymat yo'q"// `int` turidagi` variant`s bo'lgan o'zgaruvchilarni aniqlangruxsat bering to'liq = Biroz 42ruxsat bering bo'sh = Yo'q// compute_v1 to'liq -> qiymati: 42hisoblash_v1 to'liq |> printfn "compute_v1 to'liq ->% s"// compute_v1 empty -> qiymat yo'qhisoblash_v1 bo'sh |> printfn "compute_v1 bo'sh ->% s"// compute_v2 to'liq -> qiymati: 42hisoblash_v2 to'liq |> printfn "compute_v2 to'liq ->% s"// compute_v2 empty -> qiymat yo'qhisoblash_v2 bo'sh |> printfn "compute_v2 bo'sh ->% s"

Xaskell

- "Funksiya" dekonstruktsiya qilish uchun ushbu moslama naqshga mos keladihisoblash V1 :: Balki Int -> Iphisoblash V1 (Faqat x) = "Qiymat:" ++ ko'rsatish xhisoblash V1 Hech narsa yo'q  = "Qiymat yo'q"- Ushbu funktsiya o'rnatilgan "katlama" funktsiyasidan foydalanadihisoblash V2 :: Balki Int -> Iphisoblash V2 = katlama (_ x -> "Qiymat:" ++ ko'rsatish x) "Qiymat yo'q"asosiy :: IO ()asosiy = qil    - "Int`" turidagi "Bəlkə" turidagi o'zgaruvchilarni aniqlang    ruxsat bering to'liq = Faqat 42    ruxsat bering bo'sh = Hech narsa yo'q    - computeV1 to'liq -> Qiymati: 42    putStrLn $ "computeV1 to'liq ->" ++ hisoblash V1 to'liq    - computeV1 to'liq -> qiymat yo'q    putStrLn $ "computeV1 bo'sh ->" ++ hisoblash V1 bo'sh    - computeV2 to'liq -> Qiymat: 42    putStrLn $ "computeV2 to'liq ->" ++ hisoblash V2 to'liq    - computeV2 to'liq -> qiymat yo'q    putStrLn $ "computeV2 bo'sh ->" ++ hisoblash V2 bo'sh

Tez

// Ushbu funktsiya `ixtiyoriy`larni dekonstruksiya qilish uchun` switch` iborasidan foydalanadifunktsiya hisoblash V1(_ tanlov: Int?) -> Ip {    almashtirish tanlov {    ish .biroz(ruxsat bering x):        qaytish "Qiymat: (x)"    ish .yo'q:        qaytish "Qiymat yo'q"    }}// Ushbu funktsiya "Majburiy emas" ni dekonstruktsiya qilish uchun ixtiyoriy bog'lanishdan foydalanadifunktsiya hisoblash V2(_ tanlov: Int?) -> Ip {    agar ruxsat bering x = tanlov {        qaytish "Qiymat: (x)"    } boshqa {        qaytish "Qiymat yo'q"    }}// `Int` tipidagi ixtiyoriy` bo'lgan o'zgaruvchilarni aniqlangruxsat bering to'liq: Int? = 42ruxsat bering bo'sh: Int? = nol// computeV1 (to'liq) -> Qiymat: 42chop etish("computeV1 (to'liq) ->(hisoblash V1(to'liq))")// computeV1 (bo'sh) -> qiymat yo'qchop etish("computeV1 (bo'sh) ->(hisoblash V1(bo'sh))")// computeV2 (to'liq) -> Qiymat: 42chop etish("computeV2 (to'liq) ->(hisoblash V2(to'liq))")// computeV2 (bo'sh) -> qiymat yo'qchop etish("computeV2 (bo'sh) ->(hisoblash V2(bo'sh))")

Zang

// Ushbu funktsiya "Option`s" ni dekonstruktsiya qilish uchun "match`" ifodasini ishlatadifn hisoblash_v1(tanlov: &Variant<i32>)-> Ip {o'yintanlov{Biroz(x)=>format!("Qiymat: {}",x),Yo'q=>"Qiymat yo'q".egalik(),}}// Ushbu funktsiya "Option`s" ni dekonstruksiya qilish uchun "if let`" ifodasini ishlatadifn hisoblash_v2(tanlov: &Variant<i32>)-> Ip {agarruxsat beringBiroz(x)=tanlov{format!("Qiymat: {}",x)}boshqa{"Qiymat yo'q".egalik()}}// Ushbu funktsiya o'rnatilgan "map_or" usulidan foydalanadifn hisoblash_v3(tanlov: &Variant<i32>)-> Ip {tanlov.xarita_va("Qiymat yo'q".egalik(),|x|format!("Qiymat: {}",x))}fn asosiy(){// `i32` turidagi` Option`s bo'lgan o'zgaruvchilarni aniqlangruxsat beringto'liq=Biroz(42);ruxsat beringbo'sh: Variant<i32>=Yo'q;// compute_v1 (& to'liq) -> Qiymat: 42println!("compute_v1 (va to'liq) -> {}",hisoblash_v1(&to'liq));// compute_v1 (& empty) -> qiymat yo'qprintln!("compute_v1 (& empty) -> {}",hisoblash_v1(&bo'sh));// compute_v2 (& to'liq) -> Qiymat: 42println!("compute_v2 (va to'liq) -> {}",hisoblash_v2(&to'liq));// compute_v2 (& empty) -> qiymat yo'qprintln!("compute_v2 (& empty) -> {}",hisoblash_v2(&bo'sh));// compute_v3 (& to'liq) -> Qiymat: 42println!("compute_v3 (va to'liq) -> {}",hisoblash_v3(&to'liq));// compute_v3 (& empty) -> qiymat yo'qprintln!("compute_v3 (& empty) -> {}",hisoblash_v3(&bo'sh))}

Nim

Import imkoniyatlari# Ushbu prok "Option`s" ni buzish uchun o'rnatilgan "isSome" va "get" proclaridan foydalanadiprok hisoblash(tanlov: Variant[int]): mag'lubiyat =  agar tanlov.ba'zi:    "Qiymat:" & $tanlov.olish  boshqa:    "Qiymat yo'q"# "Int" turidagi "ixtiyoriy" o'zgaruvchilarni aniqlangruxsat bering  to'liq = biroz(42)  bo'sh = yo'q(int)# hisoblash (to'liq) -> Qiymat: 42aks sado "hisoblash (to'liq) ->", hisoblash(to'liq)# hisoblash (bo'sh) -> qiymat yo'qaks sado "hisoblash (bo'sh) ->", hisoblash(bo'sh)

Shuningdek qarang

Adabiyotlar

  1. ^ Milewski, Bartosz (2015-01-13). "Ma'lumotlarning oddiy algebraik turlari". Bartosz Milevskiyning dasturlash kafesi. Sumning turlari. "Biz, ehtimol, quyidagicha kodlashimiz mumkin edi: ma'lumotlar, ehtimol, a = Either () a". Arxivlandi asl nusxasidan 2019-08-18. Olingan 2019-08-18.
  2. ^ "Bir musht monada - Sizga katta yaxshilik uchun Haskellni o'rganing!". www.learnyouahaskell.com. Olingan 2019-08-18.
  3. ^ Xatton, Grem (2017 yil 25-noyabr). "Monad nima?". Computerphile Youtube. Olingan 18-avgust, 2019.
  4. ^ "Balki · Elm bilan tanishish". guide.elm-lang.org.
  5. ^ "Julia v0.7.0 nashr versiyasi · Julia tili". docs.julialang.org.
  6. ^ "Null Safety - Kotlin dasturlash tili". Olingan 2016-08-01.
  7. ^ "Apple Developer Documentation". developer.apple.com. Olingan 2020-09-06.
  8. ^ Martin Oderskiy; Lex qoshiq; Bill Venners (2008). Scala-da dasturlash. Artima Inc., 282-284-betlar. ISBN  978-0-9815316-0-1. Olingan 6 sentyabr 2011.