อ่าน 6 นาที
ML (ภาษาโปรแกรม)
ML (Meta Language) คือ เมตาภาษา ที่พัฒนาขึ้นสำหรับ โปรแกรมพิสูจน์ทฤษฎีบท LCF ของเอดินบะระ ในช่วงทศวรรษ 1970 เป็น ภาษาฟังก์ชันแบบ กำหนดประเภทคงที่ ในยุคแรกๆ ที่มี...
ML (ภาษาโปรแกรม)
| เอ็มแอล | |
|---|---|
| กระบวนทัศน์ | รูปแบบหลากหลาย : เชิงฟังก์ชัน , ทั่วไป , เชิงคำสั่ง , เชิงโต้ตอบ |
| ออกแบบโดย | โรบิน มิลเนอร์และบุคคลอื่นๆ ที่มหาวิทยาลัยเอดินบะระ |
| ปรากฏครั้งแรก | พ.ศ. 2516 |
| วินัยในการพิมพ์ | อนุมานได้ , คงที่ , แข็งแกร่ง |
| ภาษาถิ่น | |
| ML แบบพึ่งพา , ML แบบขี้เกียจ , ATS | |
| ได้รับอิทธิพลจาก | |
| ISWIM , POP-2 , PAL , GEDANKEN [ 1 ] | |
| ได้รับอิทธิพล | |
| Caml , Clojure , Cyclone , C++ , Elm , [ 2 ] Erlang , F# , F* , Haskell , Idris , Kotlin , Miranda , Nemerle , [ 3 ] OCaml , Opa , Rocq , Rust , Scala , Standard ML | |
ML (Meta Language) คือเมตาภาษาที่พัฒนาขึ้นสำหรับโปรแกรมพิสูจน์ทฤษฎีบท LCF ของเอดินบะระในช่วงทศวรรษ 1970 เป็นภาษาฟังก์ชันแบบกำหนดประเภทคงที่ ในยุคแรกๆ ที่มีการอนุมานประเภทแบบโพลีมอร์ฟิกใน รูปแบบ ฮินด์ลีย์-มิลเนอร์และคุณสมบัติอื่นๆ เช่นข้อยกเว้นและตัวแปรที่เปลี่ยนแปลงได้ [ 1 ] การออกแบบของ ML ใน LCF เป็นแรงบันดาลใจโดยตรงให้กับตระกูล ML ในภายหลัง (โดยเฉพาะStandard ML , Camlและอนุพันธ์ของพวกมัน) และมีอิทธิพลต่อการพัฒนาภาษาฟังก์ชันในเวลาต่อมา[ 4 ]
ประวัติศาสตร์
ML เริ่มพัฒนาโดยRobin Milnerเมื่อเขาเดินทางมาถึงมหาวิทยาลัยเอดินบะระในปี 1973 โดยได้รับความช่วยเหลือจากผู้ช่วยวิจัย Lockwood Morris และ Malcolm Newey ซึ่งทั้งคู่เป็นนักวิจัยหลังปริญญา เอก จาก Stanford ที่ Milner จ้าง[ 5 ] Michael Gordon , Christopher Wadsworth และนักศึกษาปริญญาโทคนอื่นๆ เข้าร่วมการวิจัยในปี 1975 [ 4 ]ในทางประวัติศาสตร์ ML ถูกคิดค้นขึ้นเพื่อพัฒนากลยุทธ์การพิสูจน์ในโปรแกรมพิสูจน์ทฤษฎีบท LCF และสืบทอดจาก Stanford LCFรุ่นก่อนหน้าโดยพยายามแก้ไขปัญหาเกี่ยวกับการใช้พื้นที่และความสามารถในการขยายการพิสูจน์ ML ทำหน้าที่เป็นทั้งภาษาเมตา (จึงเป็นที่มาของชื่อ) และภาษาคำสั่ง ( REPL ) สำหรับระบบ LCF PPLAMBDAซึ่งเป็นภาษาที่ในเชิงแนวคิดเป็นการผสมผสานระหว่างแคลคูลัสเชิงประพจน์ลำดับที่หนึ่งและแคลคูลัสแลมบ์ดาแบบโพลีมอร์ฟิกที่มีการกำหนดประเภทอย่างง่ายเป็นภาษาพื้นฐานที่ใช้ในการสร้างข้อความทฤษฎีบทโดยตรงมากขึ้น[ 1 ]
ขณะที่ ML กำลังได้รับการพัฒนา Milner ได้เขียนบทความเรื่อง"ทฤษฎีของโพลีมอร์ฟิซึมประเภทในการเขียนโปรแกรม"ในปี 1978 ซึ่งได้วางแนวคิดเกี่ยวกับความหมายของการที่โปรแกรมจะมีประเภทที่ดีในบริบทของระบบประเภทโพลีมอร์ฟิก (ทั่วไป) เขาใช้ ML เป็นกรณีศึกษาการประยุกต์ใช้ทฤษฎีที่พัฒนาขึ้น และได้บันทึกถึงความท้าทายทางทฤษฎีที่เกิดขึ้นจากการพัฒนาซึ่งยังไม่ได้รับการแก้ไข[ 6 ]การออกแบบเวอร์ชันแรกของ ML ได้รับการสรุปและบันทึกไว้ในหนังสือEdinburgh LCF ในปี 1979 โดย Milner ร่วมกับ Gordon และ Wadsworth [ 5 ] [ 1 ]
หลังจากที่Edinburgh LCFก่อตั้งขึ้นพร้อมกับการตีพิมพ์ชื่อเดียวกัน ความสนใจในภาษาก็เพิ่มมากขึ้น และมีการพัฒนาการใช้งานหลายรูปแบบ โดยมีการเปลี่ยนแปลงเล็กน้อยในด้านการออกแบบและคุณสมบัติ โดยหลายฝ่ายได้ดำเนินการอยู่Luca Cardelliได้สร้างCardelli MLหรือVAX MLซึ่งในที่สุดก็พัฒนาเป็นภาษาถิ่นแบบสแตนด์อะโลนที่เหมาะสมสำหรับการคำนวณทั่วไป โดยระบุไว้ในเอกสารML under Unix [ 7 ] [ 4 ] Gérard Huetที่Inriaเริ่มทำการพอร์ตซอร์สโค้ดจาก Stanford Lisp ไปยังภาษาถิ่นต่างๆ ของ Lisp ใน "Project Formel" การพอร์ตไปยังFranz Lispได้รับการพัฒนาเพิ่มเติมโดยLarry Paulsonซึ่งเวอร์ชันของเขาในที่สุดก็ถูกเรียกว่าCambridge LCF [ 8 ] เวอร์ชัน ของ LCF นี้ได้รับการอัปเดตในภายหลังเพื่อใช้ Standard MLเวอร์ชันแรกและได้ถูกอัปโหลดไปยังGitHub [ 9 ]
ด้วยความสนใจและความตื่นเต้นเกี่ยวกับ ML, LCF และเทคโนโลยีอื่นๆ ที่เกี่ยวข้องในขณะนั้น เช่น ภาษาโปรแกรมHopeซึ่งเกิดขึ้นหลังจากการเปิดตัวEdinburgh LCFและการพัฒนาอื่นๆ ในขณะนั้น จึงมีการจัดประชุมขึ้นในหัวข้อ "ML, LCF และ Hope" ในเดือนพฤศจิกายน พ.ศ. 2525 มีการหยิบยกข้อกังวลเกี่ยวกับการแบ่งแยกทั้งด้านการออกแบบและการนำไปใช้ซึ่งนำไปสู่การทำงานซ้ำซ้อนขึ้นมาหารือในการประชุมครั้งนี้ แม้ว่า Milner ดูเหมือนจะเปิดรับจิตวิญญาณของการทดลองในการประชุม แต่ก็มีการหารือและการประชุมเพิ่มเติมระหว่างBernard Sufrinและ Milner โดย Sufrin ได้กระตุ้นให้ Milner รวมการออกแบบของ ML เข้าด้วยกัน การติดต่อสื่อสารเหล่านี้ได้รับการอ้างอิงในร่างฉบับที่สองของข้อเสนอของ Milner สำหรับ Standard ML ในภายหลัง[ 4 ]
ภาพรวม
แรงบันดาลใจที่โดดเด่นที่สุดของไวยากรณ์ของ ML สามารถสืบย้อนไปถึงISWIMซึ่งเป็นภาษาที่ถูกอธิบายว่าเป็น " แคลคูลัสแลมบ์ดาที่มีน้ำตาลทางไวยากรณ์" [ 4 ] ML ได้รับการออกแบบด้วยระบบประเภทคงที่ที่ แข็งแกร่ง ซึ่งอนุญาตให้ผู้ใช้กำหนดประเภทนามธรรมด้วยโพลีมอร์ฟิซึมแบบพารามิเตอร์และได้รับการตรวจสอบในเวลาคอมไพล์[ 1 ]นอกจากนี้ยังมีการอนุมานประเภทอัตโนมัติ ซึ่งทำให้ ML ใช้งานง่ายเหมือนภาษาไดนามิกในสมัยนั้น เช่น Lisp หรือ POP-2 โดยไม่ต้องมีคำอธิบายประกอบประเภทที่ชัดเจน[ 4 ]
ตัวอย่าง
ตัวอย่างต่อไปนี้ได้มาจากEdinburgh LCF อย่างใกล้ชิด โดยแสดงภาพรวมคร่าวๆ ของไวยากรณ์และคุณลักษณะของ ML #อักขระที่ต้นบรรทัดแสดงถึงข้อมูลที่ผู้ใช้ป้อน และบรรทัดที่ไม่มีอักขระดังกล่าวคือการตอบสนองของระบบที่แสดงค่าและประเภทที่อนุมานได้ โปรดทราบว่าส่วนนี้ไม่ได้มีจุดประสงค์เพื่อนำเสนอคุณลักษณะของภาษา ML อย่างครบถ้วน แต่เป็นเพียงส่วนย่อยเพื่อให้เข้าใจถึงภาษา โปรดดูEdinburgh LCFสำหรับคำจำกัดความที่เข้มงวดกว่า[ 1 ]
นิพจน์จะถูกประเมินโดยการพิมพ์นิพจน์นั้นตามด้วยเครื่องหมาย;;& และอักขระขึ้นบรรทัดใหม่ ตัวระบุitจะเก็บผลลัพธ์ของนิพจน์ที่ประเมินครั้งล่าสุดการผูกค่าจะเริ่มต้นด้วย เครื่องหมาย let& และสามารถสร้างการผูกค่าหลายรายการพร้อมกันได้โดยการรวมเข้าด้วยกันโดยใช้andคำหลัก & หรือโดยการสร้างคู่ (ซึ่งมีประเภทผลิตภัณฑ์ที่จะกล่าวถึงในตัวอย่างต่อไป) ทางด้านขวามือ ซึ่งจะถูกจับคู่รูปแบบทางด้านซ้าย:
#2+3;; 5 : int #ให้ x = มัน;; x = 5 : int #กำหนดให้ y = 2*5 และ z = 7;; y = 10 : int z = 7 : int #let x,y,z = y,x,2;; x = 10 : int y = 5 : int z = 2 : int
ฟังก์ชันถูกกำหนดด้วย `undefined` letการเรียกใช้ฟังก์ชันมีลำดับความสำคัญสูงกว่าตัวดำเนินการทางคณิตศาสตร์ ดังนั้น `undefined` จึงf 3 + 4หมายถึง(f 3) + 4`undefined` ฟังก์ชันที่กำหนดด้วยพารามิเตอร์หลายตัวเรียกว่า`curried`ดังนั้นการส่งพารามิเตอร์หนึ่งตัวเข้าไปในฟังก์ชันจะคืนค่าฟังก์ชันที่รับพารามิเตอร์ตัวที่สอง และต่อไปเรื่อยๆ ฟังก์ชันแบบเรียกซ้ำต้องการ `undefined` letrecเพื่อให้ชื่อฟังก์ชันอยู่ในขอบเขตภายในตัวฟังก์ชันเอง ไวยากรณ์สำหรับฟังก์ชันนิรนามคล้ายกับแคลคูลัสแลมบ์ดา โดยใช้ `undefined` \สำหรับแลมบ์ดา และ ` .undefined` เพื่อแยกอาร์กิวเมนต์ออกจากนิพจน์:
#ให้เพิ่ม xy = x+y;; เพิ่ม = - : (int -> (int -> int)) #เพิ่ม 3;; - : (จำนวนเต็ม -> จำนวนเต็ม) #it 4;; 7 : int #letrec fact n = if n = 0 then 1 else n * fact(n-1);; ข้อเท็จจริง = - : (จำนวนเต็ม -> จำนวนเต็ม) #ข้อเท็จจริงที่ 4;; 24 : อินท์ #(\x.x+1) 3;; 4 : int
ลิสต์ใช้เครื่องหมายเซมิโคลอนคั่นระหว่างองค์ประกอบhdและtlเป็นฟังก์ชันในตัวที่ส่งคืนส่วนหัวและส่วนท้าย โดย.คือcons (เพิ่มเข้าไปด้านหน้า) และ@คือ append ฟังก์ชันต่างๆ เช่นhdเป็นแบบโพลีมอร์ฟิก—ML ใช้ตัวแปรประเภททั่วไป ( *, **, เป็นต้น) เพื่อแสดงสิ่งนี้:
#ให้ m = [1;2;3;4];; m = [1; 2; 3; 4] : (รายการจำนวนเต็ม) #hd m, tl m;; 1, [2; 3; 4] : (int # (int list)) #0.ม. @ [5;6];; [0; 1; 2; 3; 4; 5; 6] : (รายการจำนวนเต็ม) #hd;; - : ((* รายการ) -> *) #แผนที่ (\xx*x) [1;2;3;4];; [1; 4; 9; 16] : (รายการจำนวนเต็ม)
ตัวแปรที่เปลี่ยนแปลงได้จะถูกประกาศด้วยletrefและอัปเดตด้วยคำหลัก เป็นส่วนหนึ่งของโครงสร้างลูป if-then ซึ่งจะวนซ้ำทุกครั้งที่เงื่อนไขไม่เป็นจริง: :=loopif
#ให้ข้อเท็จจริง n = # letref count = n และ result = 1 # ในกรณีที่จำนวนเท่ากับ 0 # จากนั้นผลลัพธ์ # วนลูปนับผลลัพธ์ := จำนวนนับ - 1, จำนวนนับ * ผลลัพธ์; ข้อเท็จจริง = - : (จำนวนเต็ม -> จำนวนเต็ม) #ข้อเท็จจริงที่ 4;; 24 : อินท์
โทเค็นเป็นประเภทสตริงของ ML ซึ่งคั่นด้วยเครื่องหมาย`; เครื่องหมายแบ็กติ๊กสองตัวจะสร้างรายการโทเค็น การใช้งานโทเค็นที่พบบ่อยคือการระบุความล้มเหลวด้วย `@exception` failwithซึ่งเป็นคำหลักที่ใช้เพื่อสร้างข้อยกเว้นด้วยโทเค็นที่ระบุอย่างชัดเจน และ `@exception` ?ใช้เพื่อดักจับข้อยกเว้นนั้น:
นี่คือโทเค็น;; นี่คือโทเค็น : tok #``นี่คือรายการโทเค็น``;; [`this`; `is`; `a`; `token`; `list`] : (รายการโทเค็น) #ให้ครึ่งหนึ่งของ n = # ถ้า n = 0 ให้ล้มเหลวด้วยค่า `ศูนย์` # มิเช่นนั้น ให้ m = n/2 # ในเงื่อนไข if n = 2*m แล้ว m มิฉะนั้น failwith `odd`;; ครึ่ง = - : (จำนวนเต็ม -> จำนวนเต็ม) #ครึ่ง 4;; 2 : int #ครึ่งที่ 3;; การประเมินล้มเหลว แปลก #ครึ่ง 3 ? 0;; 0 : int
ประเภทนามธรรม (Abstract types) ประกาศด้วย `@` abstypeซึ่งจะสร้างประเภทใหม่และกำหนดฟังก์ชันที่ใช้ทำงานกับประเภทนั้น โดยซ่อนโครงสร้างภายใน (ประเภทที่เป็นรูปธรรมที่ใช้สร้างมันขึ้นมา) ไว้ ประเภทนามธรรมแบบเรียกซ้ำ (Abstract recursive types) ประกาศด้วย `@` absrectypeซึ่งอนุญาตให้ใช้ประเภทนั้นในคำจำกัดความของตัวเองได้ มีคีย์เวิร์ดที่คล้ายกันคือ `@` lettypeซึ่งใช้สำหรับการตั้งชื่อแทนประเภท พื้นฐานมากขึ้น ต่อ ไปนี้เป็นประเภทนามธรรมแบบเรียกซ้ำที่กำหนดโครงสร้างต้นไม้ไบนารีพร้อมการดำเนินการพื้นฐานบางอย่าง:
#absrectype (*, **) tree = * + ** # (*, **) tree # (*, **) tree # ด้วย tiptree x = abstree(inl x) # และ comptree (y, t1, t2) = abstree(inr(y, t1, t2)) # และ istip t = isl(reptree t) # และ tipof t = outl(reptree t) ? failwith `tipof` # และ labelof t = fst(outr(reptree t)) ? failwith `labelof` # และ sonsof t = snd(outr(reptree t)) ? failwith `sonsof`;; tiptree = - : (* -> (*, **) tree) comptree = - : ((** # (*, **) tree # (*, **) tree) -> (*, **) tree) istip = - : ((*, **) tree -> bool) tipof = - : ((*, **) tree -> *) labelof = - : ((*, **) tree -> **) sonsof = - : ((*, **) tree -> ((*, **) tree # (*, **) tree))
ภายในคำจำกัดความของการดำเนินการ ( withบล็อก) สามารถนำชื่อประเภทมาขึ้นต้นด้วยabsเพื่อ บรรจุค่า ลงในประเภท และrepเพื่อแกะค่าออกจากประเภท ตัวอักษร+และ#ในคำจำกัดความของประเภท หมายถึงประเภทผลรวม (ยูเนียนที่มีแท็ก) และประเภทผลคูณ (ทูเปิล) ตามลำดับ โดยที่#มีลำดับความสำคัญสูงกว่า
ML บน LCF มีฟังก์ชันช่วยเหลือหลายอย่างที่ใช้ในตัวอย่างข้างต้น+ฟังก์ชันเหล่านี้ ทำงานกับประเภทผลรวม inlโดยinrจะแทรกค่าเข้าไปในด้านซ้ายหรือด้านขวาของประเภทผลรวม ฟังก์ชัน `extract` จะดึงค่า outlจากค่าที่แทรกเข้ามาทางซ้าย (จะล้มเหลวหากได้รับค่าที่แทรกเข้ามาทางขวา) และoutrฟังก์ชัน `extract` จะดึงค่าจากค่าที่แทรกเข้ามาทางขวา (จะล้มเหลวหากได้รับค่าที่แทรกเข้ามาทางซ้าย) สำหรับประเภทผลคูณ#ฟังก์ชันการดึงค่าคือ `extract` fstและsnd`extract` ซึ่งจะดึงส่วนประกอบแรกและส่วนประกอบที่สองของคู่ ประเภทผลคูณถูกสร้างขึ้นโดยใช้ตัวดำเนินการคอมมา ในตัวอย่างต้นไม้ข้างต้น ฟังก์ชัน `extract` comptreeรับพารามิเตอร์เดียวที่เป็นรูปแบบคู่(y, t1, t2)ซึ่งจะแยกคู่นั้นออกเป็นสามส่วนประกอบ
ดูเพิ่มเติม
อ่านเพิ่มเติม
- Christoph Kreitz, Vincent Rahli, บทนำสู่ ML แบบคลาสสิก ( เก็บถาวรเมื่อวันที่ 8 กรกฎาคม 2024 ), มหาวิทยาลัยคอร์เนล, ตุลาคม 2011. บันทึกการบรรยายเกี่ยวกับภาษาถิ่นของ ML ที่มีลักษณะใกล้เคียงกับLCF/ ML
- Luca Cardelli, เอกสาร ( เก็บถาวรเมื่อวันที่ 25 มกราคม 2026 ), มหาวิทยาลัยออกซ์ฟอร์ด แสดงรายการเอกสารที่เกี่ยวข้องกับการพัฒนา Cardelli ML/ML ภายใต้ VMS/ML ภายใต้ Unix
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ ML (ภาษาโปรแกรม)
ML (Meta Language) คือ เมตาภาษา ที่พัฒนาขึ้นสำหรับ โปรแกรมพิสูจน์ทฤษฎีบท LCF ของเอดินบะระ ในช่วงทศวรรษ 1970 เป็น ภาษาฟังก์ชันแบบ กำหนดประเภทคงที่ ในยุคแรกๆ ที่มี...
ประวัติศาสตร์
ML เริ่มพัฒนาโดย Robin Milner เมื่อเขาเดินทางมาถึง มหาวิทยาลัยเอดินบะระ ในปี 1973 โดยได้รับความช่วยเหลือจากผู้ช่วยวิจัย Lockwood Morris และ Malcolm Newey ซึ่งทั้งคู่ เป็นนักวิจัยหลังปริญญา เอก จาก Stanford ที่ Milner จ้าง [ 5 ] Michael Gordon , Christopher...
ภาพรวม
แรงบันดาลใจที่โดดเด่นที่สุดของไวยากรณ์ของ ML สามารถสืบย้อนไปถึง ISWIM ซึ่งเป็นภาษาที่ถูกอธิบายว่าเป็น " แคลคูลัสแลมบ์ดา ที่มีน้ำตาลทางไวยากรณ์" [ 4 ] ML ได้รับการออกแบบด้วย ระบบประเภทคงที่ที่ แข็งแกร่ง ซึ่งอนุญาตให้ผู้ใช้กำหนด ประเภทนามธรรม ด้วย...
ตัวอย่าง
ตัวอย่างต่อไปนี้ได้มาจาก Edinburgh LCF อย่างใกล้ชิด โดยแสดงภาพรวมคร่าวๆ ของไวยากรณ์และคุณลักษณะของ ML # อักขระที่ต้นบรรทัดแสดงถึงข้อมูลที่ผู้ใช้ป้อน และบรรทัดที่ไม่มีอักขระดังกล่าวคือการตอบสนองของระบบที่แสดงค่าและประเภทที่อนุมานได้...