لغة الآلة القياسية
لغة البرمجة القياسية ML ( SML ) هي لغة برمجة وظيفية عالية المستوى ، متعددة الأغراض ، ونمطية ، مع خاصية التحقق من الأنواع واستنتاجها في وقت الترجمة . وهي شائعة الاستخدام في كتابة المترجمات ، وأبحاث لغات البرمجة ، وتطوير برامج إثبات النظريات .
لغة Standard ML هي لهجة حديثة من لغة ML ، وهي اللغة المستخدمة في مشروع إثبات النظريات " منطق الدوال القابلة للحساب" (LCF). وتتميز هذه اللغة عن غيرها من اللغات واسعة الانتشار بوجود مواصفات رسمية لها ، مُقدمة على شكل قواعد كتابة ودلالات تشغيلية في "تعريف Standard ML" ، الذي صدر لأول مرة عام 1990، مع إصدار مراجعة ثانية وأخيرة عام 1997. [ 5 ] [ 6 ]
لغة
لغة Standard ML هي لغة برمجة وظيفية ذات بعض الخصائص غير النقية. تتكون البرامج المكتوبة بلغة Standard ML من تعابير بدلاً من عبارات أو أوامر، على الرغم من أن بعض التعابير من نوع وحدة يتم تقييمها فقط من حيث آثارها الجانبية .
الوظائف
كما هو الحال في جميع اللغات الوظيفية، فإن إحدى السمات الرئيسية للغة Standard ML هي الدالة ، التي تُستخدم للتجريد. ويمكن التعبير عن دالة المضروب كما يلي:
دالة مضروب n = إذا كان n = 0 فإن 1 وإلا n * مضروب ( n - 1 )استنتاج النوع
يجب على مُصرّف لغة SML استنتاج النوع الثابت دون الحاجة إلى تعليقات توضيحية للأنواع من قِبل المستخدم. عليه أن يستنتج أن هذا النوع يُستخدم فقط مع التعبيرات العددية الصحيحة، وبالتالي يجب أن يكون هو نفسه عددًا صحيحًا، وأن جميع التعبيرات الطرفية هي تعبيرات عددية صحيحة.valfactorial:int->intn
التعريفات التصريحية
يمكن التعبير عن نفس الوظيفة باستخدام تعريفات الوظائف الشرطية حيث يتم استبدال الشرط if - then - else بقوالب لدالة المضروب التي يتم تقييمها لقيم محددة:
دالة مضروب 0 = 1 | مضروب n = n * مضروب ( n - 1 )التعريفات الإلزامية
أو بشكل متكرر:
دالة حساب المضروب n = let val i = ref n and acc = ref 1 in while !i > 0 do ( acc := !acc * !i ; i := !i - 1 ); !acc endدوال لامدا
أو كدالة لامدا:
val rec factorial = fn 0 => 1 | n => n * factorial ( n - 1 )هنا، تُدخل الكلمة المفتاحية valربطًا بين مُعرّف وقيمة، fnوتُدخل دالة مجهولة ، recوتسمح بأن يكون التعريف مرجعيًا ذاتيًا.
التعريفات المحلية
إن تغليف حلقة تكرارية ضيقة تحافظ على الثابت مع معلمات تراكمية واحدة أو أكثر داخل دالة خارجية خالية من الثابت، كما هو موضح هنا، هو أسلوب شائع في لغة ML القياسية.
باستخدام دالة محلية، يمكن إعادة كتابتها بأسلوب أكثر كفاءة يعتمد على الاستدعاء الذاتي الذيل:
دالة محلية loop ( 0 , acc ) = acc | loop ( m , acc ) = loop ( m - 1 , m * acc ) في دالة factorial n = loop ( n , 1 ) نهايةمرادفات النوع
يُعرَّف مرادف النوع باستخدام الكلمة المفتاحية type. فيما يلي مرادف نوع للنقاط على مستوى ، ودوال لحساب المسافات بين نقطتين، ومساحة مثلث ذي زوايا معينة وفقًا لصيغة هيرون . (ستُستخدم هذه التعريفات في الأمثلة اللاحقة).
نوع الموقع = حقيقي * حقيقيدالة المربع ( س : عدد حقيقي ) = س * سدالة المسافة ( س ، ص ) ( س' ، ص' ) = جذر ( مربع ( س ' - س ) + مربع ( ص' - ص ) )دالة هيرون ( أ ، ب ، ج ) = let val x = dist a b val y = dist b c val z = dist a c val s = ( x + y + z ) / 2.0 in Math.sqrt ( s * ( s - x ) * ( s - y ) * ( s - z ) ) endأنواع البيانات الجبرية
توفر لغة Standard ML دعمًا قويًا لأنواع البيانات الجبرية (ADT). يمكن اعتبار نوع البيانات اتحادًا منفصلاً من الصفوف (أو "مجموع حاصل الضرب"). تتميز هذه الأنواع بسهولة تعريفها واستخدامها، ويعود ذلك بشكل كبير إلى مطابقة الأنماط ، بالإضافة إلى فحص شمولية الأنماط وفحص تكرارها في معظم تطبيقات Standard ML .
في لغات البرمجة كائنية التوجه ، يمكن التعبير عن الاتحاد المنفصل باستخدام تسلسلات هرمية للفئات . مع ذلك، وعلى عكس التسلسلات الهرمية للفئات ، فإن أنواع البيانات المجردة (ADTs) مغلقة . وبالتالي، فإن قابلية توسيع أنواع البيانات المجردة مستقلة عن قابلية توسيع التسلسلات الهرمية للفئات. يمكن توسيع التسلسلات الهرمية للفئات بإضافة فئات فرعية جديدة تُنفذ نفس الواجهة، بينما يمكن توسيع وظائف أنواع البيانات المجردة لمجموعة ثابتة من المُنشئات. انظر مسألة التعبير .
يتم تعريف نوع البيانات باستخدام الكلمة المفتاحية datatype، كما في:
datatype shape = دائرة من loc * real (* المركز ونصف القطر *) | مربع من loc * real (* الزاوية العلوية اليسرى وطول الضلع؛ محاذي للمحور *) | مثلث من loc * loc * loc (* الزوايا *)لاحظ أن مرادف النوع لا يمكن أن يكون تكراريًا؛ فأنواع البيانات ضرورية لتعريف المُنشئات التكرارية. (هذا ليس محل نقاش في هذا المثال).
مطابقة الأنماط
تُطابق الأنماط بالترتيب الذي عُرّفت به. يستطيع مبرمجو لغة C استخدام الاتحادات الموسومة ، والتوزيع بناءً على قيم الوسوم، للقيام بما تفعله لغة ML مع أنواع البيانات ومطابقة الأنماط. مع ذلك، فبينما سيكون برنامج C المُزوّد بفحوصات مناسبة، من ناحية ما، بنفس قوة برنامج ML المقابل، ستكون هذه الفحوصات ديناميكية بالضرورة؛ إذ توفر الفحوصات الثابتة في ML ضمانات قوية حول صحة البرنامج في وقت الترجمة.
يمكن تعريف وسائط الدالة كأنماط على النحو التالي:
دالة حساب مساحة الدائرة ( النقطة ، نصف القطر ) = π × مربع نصف القطر | مساحة المربع (النقطة، المسافة ) = مربع المسافة | مساحة المثلث ( نقطة ) = مربع نقطة ( انظر أعلاه)إن ما يسمى بـ "الصيغة الشرطية" لتعريف الدالة، حيث يتم تعريف الوسائط كأنماط، ليس سوى اختصار نحوي لتعبير الحالة:
شكل المساحة الممتعة = حالة شكل الدائرة ( _, r ) => Math.pi * مربع r | مربع (_, s ) = > مربع s | مثلث p = > heron pالتحقق من الشمولية
سيضمن فحص شمولية الأنماط أن كل مُنشئ لنوع البيانات يتطابق مع نمط واحد على الأقل.
النمط التالي ليس شاملاً:
fun center ( Circle ( c , _)) = c | center ( Square (( x , y ), s )) = ( x + s / 2.0 , y + s / 2.0 )لا يوجد نمط محدد للحالة Triangleفي centerالدالة. سيصدر المترجم تحذيرًا بأن تعبير الحالة غير شامل، وإذا Triangleتم تمرير قيمة a إلى هذه الدالة أثناء التشغيل، فسيتم رفع استثناء.exceptionMatch
التحقق من التكرار
النمط الموجود في الجزء الثاني من الدالة التالية (التي لا معنى لها) زائد عن الحاجة:
دالة f ( دائرة (( x , y ), r )) = x + y | f ( دائرة _) = 1.0 | f _ = 0.0أي قيمة تُطابق النمط في البند الثاني ستُطابق أيضًا النمط في البند الأول، لذا فإن البند الثاني غير قابل للوصول. وعليه، يُظهر هذا التعريف ككل تكرارًا، مما يُؤدي إلى ظهور تحذير أثناء الترجمة.
تعريف الدالة التالي شامل وغير زائد عن الحاجة:
val hasCorners = fn ( Circle _) => false | _ => trueإذا تجاوز التحكم النمط الأول ( Circle)، فإننا نعلم أن الشكل يجب أن يكون إما a Squareأو a Triangle. في كلتا الحالتين، نعلم أن الشكل له زوايا، لذلك يمكننا العودة trueدون تمييز الشكل الفعلي.
الدوال ذات الرتبة العليا
يمكن للدوال أن تستهلك الدوال كوسائط:
دالة الخريطة f ( x , y ) = ( f x , f y )يمكن للدوال أن تُنتج دوالًا أخرى كقيم مُعادة:
دالة ثابتة k = ( fn _ => k )يمكن للدوال أيضًا أن تستهلك وتنتج الدوال:
fun compose ( f , g ) = ( fn x => f ( g x ))تُعد الدالة الموجودة في المكتبةList.map الأساسية واحدة من أكثر الدوال عالية الرتبة استخدامًا في لغة Standard ML:
دالة map _ [] = [] | map f ( x :: xs ) = f x :: map f xsتنفيذ أكثر كفاءة باستخدام الاستدعاء الذاتي الذيل List.foldl:
دالة map f = List . rev o List . foldl ( fn ( x , acc ) => f x :: acc ) []الاستثناءات
تُثار الاستثناءات باستخدام الكلمة المفتاحية raiseويتم التعامل معها باستخدام handleبنية مطابقة الأنماط. يمكن لنظام الاستثناءات تنفيذ الخروج غير المحلي ؛ هذه التقنية المُحسِّنة مناسبة لوظائف مثل ما يلي.
استثناء محلي Zero ؛ val p = fn ( 0 , _) => raise Zero | ( a , b ) => a * b in fun prod xs = List . foldl p 1 xs handle Zero => 0 endعند حدوث استثناء، يخرج التحكم من الدالة تمامًا. لنفترض البديل: ستُعاد القيمة 0، ثم تُضرب في العدد الصحيح التالي في القائمة، ثم تُعاد القيمة الناتجة (وهي حتمًا 0)، وهكذا. يسمح حدوث الاستثناء بتجاوز سلسلة الإطارات بأكملها وتجنب العمليات الحسابية المرتبطة بها. لاحظ استخدام الشرطة السفلية (_ ) كنمط بدل.exceptionZeroList.foldl_
يمكن الحصول على نفس التحسين باستخدام استدعاء الذيل .
دالة محلية p a ( 0 :: _) = 0 | p a ( x :: xs ) = p ( a * x ) xs | p a [] = a in val prod = p 1 endنظام الوحدات
يُتيح نظام الوحدات المتقدم في لغة Standard ML تقسيم البرامج إلى هياكل مُنظمة هرميًا ذات تعريفات منطقية للأنواع والقيم. لا توفر الوحدات التحكم في مساحة الأسماء فحسب ، بل توفر أيضًا التجريد، بمعنى أنها تسمح بتعريف أنواع البيانات المجردة . يتألف نظام الوحدات من ثلاثة عناصر نحوية رئيسية: التوقيعات، والهياكل، والدوال.
التوقيعات
التوقيع هو واجهة ، يُنظر إليه عادةً على أنه نوع لبنية ما؛ فهو يُحدد أسماء جميع الكيانات التي تُوفرها البنية، وعدد معاملات كل مُكوّن نوعي، ونوع كل مُكوّن قيمة، وتوقيع كل بنية فرعية. تعريفات المُكوّنات النوعية اختيارية؛ أما المُكوّنات النوعية التي تكون تعريفاتها مخفية فهي أنواع مجردة .
على سبيل المثال، قد يكون توقيع قائمة الانتظار كالتالي:
توقيع QUEUE = sig نوع 'a queue استثناء QueueError ؛ قيمة فارغة : 'a queue قيمة فارغة : 'a queue -> منطقي قيمة مفردة : 'a -> 'a queue قيمة من قائمة : 'a قائمة -> 'a queue قيمة إدراج : 'a * 'a queue -> 'a queue قيمة معاينة : 'a queue -> 'a قيمة إزالة : 'a queue -> 'a * 'a queue نهايةيصف هذا التوقيع وحدة نمطية توفر نوعًا متعدد الأشكال ، وقيمًا تحدد العمليات الأساسية على قوائم الانتظار.'aqueueexceptionQueueError
الهياكل
البنية هي وحدة نمطية ؛ تتكون من مجموعة من الأنواع والاستثناءات والقيم والهياكل (تسمى الهياكل الفرعية ) المعبأة معًا في وحدة منطقية.
يمكن تنفيذ بنية قائمة الانتظار على النحو التالي:
structure TwoListQueue :> QUEUE = struct type 'a queue = 'a list * 'a listاستثناء QueueError ؛val empty = ([], [])دالة isEmpty ([], []) = صحيح | isEmpty _ = خطأدالة أحادية a = ([], [ a ])دالة fromList a = ([], a )دالة إدراج ( أ ، ([]، [])) = عنصر مفرد أ | إدراج ( أ ، ( إدراج ، إخراج )) = ( أ :: إدراج ، إخراج )دالة peek (_, []) = raise QueueError | peek ( ins , outs ) = List . hd outsدالة remove (_, []) = raise QueueError | remove ( ins , [ a ] ) = ( a , ([], List.revins ) ) | remove ( ins , a :: outs ) = ( a , ( ins , outs ) ) endيُعلن هذا التعريف أن البنية تُنفذ . علاوة على ذلك، يُشير التخصيص المُبهم المُشار إليه بـ إلى أن أي أنواع غير مُعرّفة في التوقيع (أي ) يجب أن تكون مجردة، مما يعني أن تعريف الطابور كزوج من القوائم غير مرئي خارج الوحدة. تُنفذ البنية جميع التعريفات الواردة في التوقيع.structureTwoListQueuesignatureQUEUE:>type'aqueue
يمكن الوصول إلى الأنواع والقيم في بنية ما باستخدام "تدوين النقطة":
val q : string TwoListQueue . queue = TwoListQueue . empty val q' = TwoListQueue . insert ( Real . toString Math . pi , q )الدوال
الدالة الوظيفية هي دالة تربط بين هياكل البيانات المختلفة؛ أي أنها تقبل وسيطًا واحدًا أو أكثر، وعادةً ما تكون هذه الوسائط هياكل بيانات ذات توقيع محدد، وتُنتج هيكل بيانات كنتيجة لها. تُستخدم الدوال الوظيفية لتنفيذ هياكل البيانات والخوارزميات العامة .
تستخدم إحدى الخوارزميات الشائعة للبحث العرضي في الأشجار قوائم الانتظار. [ 7 ] إليك نسخة من تلك الخوارزمية مُعَلمة على بنية قائمة انتظار مجردة:
(* نقلاً عن أوكازاكي، المؤتمر الدولي لعلم النفس الوظيفي، 2000 *) الدالة BFS ( Q : QUEUE ) = بنية البيانات 'a tree = E | T من 'a * 'a tree * 'a treeدالة محلية bfsQ q = إذا كانت Q فارغة ، فإن q فارغة ، وإلا ابحث ( Q.remove q ) وابحث ( E , q ) = bfsQ q | ابحث ( T ( x , l , r ) , q ) = x :: bfsQ ( insert ( insert q l ) r ) وابحث عن q a = Q.insert ( a , q ) في دالة bfs t = bfsQ ( Q.singleton t ) نهاية نهايةبنية QueueBFS = BFS ( TwoListQueue )في هذا السياق ، لا يظهر تمثيل قائمة الانتظار. وبشكل أكثر تحديدًا، لا توجد طريقة لاختيار القائمة الأولى في قائمة الانتظار المكونة من قائمتين، إذا كان هذا هو التمثيل المستخدم بالفعل. تجعل آلية تجريد البيانات هذه عملية البحث بالعرض أولًا مستقلة تمامًا عن تنفيذ قائمة الانتظار. وهذا أمر مرغوب فيه عمومًا؛ ففي هذه الحالة، يمكن لبنية قائمة الانتظار الحفاظ بأمان على أي ثوابت منطقية تعتمد عليها صحتها خلف جدار التجريد المتين.functorBFS
أمثلة على التعليمات البرمجية
يمكن دراسة مقتطفات من كود SML بسهولة أكبر عن طريق إدخالها في مستوى أعلى تفاعلي .
مرحبا بالعالم!
فيما يلي برنامج "مرحباً بالعالم!" :
| hello.sml |
|---|
اطبع "مرحباً بالعالم! \n " ; |
| ش |
$ mlton hello.sml $ ./hello مرحباً بالعالم! |
الخوارزميات
فرز الإدراج
يمكن التعبير عن فرز الإدراج (تصاعديًا) بإيجاز على النحو التالي:intlist
دالة إدراج ( x ، []) = [ x ] | إدراج ( x ، h :: t ) = فرز x ( h ، t ) وفرز x ( h ، t ) = إذا كان x < h فإن [ x ، h ] @ t وإلا h :: إدراج ( x ، t ) قيمة فرز الإدراج = List.foldl إدراج [ ]فرز الدمج
هنا، تُطبَّق خوارزمية فرز الدمج الكلاسيكية في ثلاث دوال: split و merge و mergesort. لاحظ أيضًا غياب أنواع البيانات، باستثناء الصيغة التي تُشير إلى القوائم. سيُرتب هذا الكود قوائم من أي نوع، طالما تم تعريف دالة ترتيب متسقة. باستخدام استنتاج أنواع هيندلي-ميلنر ، يُمكن استنتاج أنواع جميع المتغيرات، حتى الأنواع المعقدة مثل نوع الدالة .op::[]cmpcmp
ينقسم
funsplitيتم تنفيذه باستخدام إغلاق ذي حالة يتناوب بين trueو false، متجاهلاً المدخلات:
fun alternator {} = let val state = ref true in fn a => !state before state := not ( !state ) end(* تقسيم قائمة إلى نصفين متقاربين، أحدهما متساوٍ في الطول، * والآخر يحتوي على عنصر إضافي. * يستغرق التنفيذ O(n) من الوقت، حيث n = |xs|. * ) fun split xs = List.partition ( alternator {} ) xsدمج
تستخدم دالة الدمج حلقة دالة محلية لتحسين الكفاءة. loopيتم تعريف الجزء الداخلي من خلال الحالات التالية: عندما تكون كلتا القائمتين غير فارغتين ( ) وعندما تكون إحدى القائمتين فارغة ( ).x::xs[]
تدمج هذه الدالة قائمتين مرتبتين في قائمة واحدة مرتبة. لاحظ كيف يتم بناء المُجمِّع accبشكل عكسي، ثم عكسه قبل إرجاعه. هذه تقنية شائعة، لأن القائمة مُمثلة كقائمة مرتبطة ؛ تتطلب هذه التقنية وقتًا أطول، لكن الأداء التقاربي ليس أسوأ.'alist
(* دمج قائمتين مرتبتين باستخدام دالة cmp. * شرط مسبق: يجب أن تكون كل قائمة مرتبة مسبقًا لكل عملية cmp. * يعمل في زمن O(n)، حيث n = |xs| + |ys|. *) دالة دمج cmp ( xs , []) = xs | دمج cmp ( xs , y :: ys ) = let دالة حلقة ( a , acc ) ( xs , []) = List . revAppend ( a :: acc , xs ) | حلقة ( a , acc ) ( xs , y :: ys ) = if cmp ( a , y ) then حلقة ( y , a :: acc ) ( ys , xs ) else حلقة ( a , y :: acc ) ( xs , ys ) in حلقة ( y , []) ( ys , xs ) endفرز الدمج
الوظيفة الرئيسية:
دالة ap f ( x , y ) = ( f x , f y )(* رتب قائمة وفقًا لعملية الترتيب المحددة cmp. * يعمل في زمن O(n log n)، حيث n = |xs|. *) fun mergesort cmp [] = [] | mergesort cmp [ x ] = [ x ] | mergesort cmp xs = ( merge cmp o ap ( mergesort cmp ) o split ) xsفرز سريع
يمكن التعبير عن خوارزمية الفرز السريع على النحو التالي. هي دالة مغلقة تستهلك عامل ترتيب .funpartop<<
infix <<دالة الفرز السريع ( op << ) = let fun part p = List.partition ( fn x => x << p ) fun sort [ ] = [ ] | sort ( p :: xs ) = join p ( part p xs ) and join p ( l , r ) = sort l @ p :: sort r in sort endمترجم تعابير الوجه
لاحظ مدى سهولة تعريف ومعالجة لغة تعبيرية صغيرة:
استثناء TyErr ؛نوع البيانات ty = IntTy | BoolTyدالة unify ( IntTy , IntTy ) = IntTy | unify ( BoolTy , BoolTy ) = BoolTy | unify (_, _) = raise TyErrنوع البيانات exp = صحيح | خطأ | عدد صحيح من عدد صحيح | ليس من exp | جمع exp * exp | شرط من exp * exp * expدالة infer True = BoolTy | infer False = BoolTy | infer ( Int _) = IntTy | infer ( Not e ) = ( assert e BoolTy ; BoolTy ) | infer ( Add ( a , b )) = ( assert a IntTy ; assert b IntTy ; IntTy ) | infer ( If ( e , t , f )) = ( assert e BoolTy ; unify ( infer t , infer f )) and assert e t = unify ( infer e , t )دالة eval True = True | eval False = False | eval ( Int n ) = Int n | eval ( Not e ) = if eval e = True then False else True | eval ( Add ( a , b )) = ( case ( eval a , eval b ) of ( Int x , Int y ) => Int ( x + y )) | eval ( If ( e , t , f )) = eval ( if eval e = True then t else f )fun run e = ( infer e ; SOME ( eval e )) handle TyErr => NONEأمثلة على استخدام التعبيرات المكتوبة بشكل صحيح والتعبيرات المكتوبة بشكل خاطئ:
val SOME ( Int 3 ) = run ( Add ( Int 1 , Int 2 )) (* صحيح النوع *) val NONE = run ( If ( Not ( Int 1 ), True , False )) (* غير صحيح النوع *)الأعداد الصحيحة ذات الدقة العشوائية
توفر هذه IntInfالوحدة عمليات حسابية للأعداد الصحيحة بدقة اختيارية. علاوة على ذلك، يمكن استخدام القيم العددية كأعداد صحيحة بدقة اختيارية دون الحاجة إلى أي تدخل من المبرمج.
البرنامج التالي ينفذ دالة مضروبية ذات دقة عشوائية:
| fact.sml |
|---|
حقيقة ممتعة n : IntInf . int = إذا كان n = 0 فإن 1 وإلا n * حقيقة ( n - 1 );fun printLine str = TextIO.output ( TextIO.stdOut , str ^ " \ n " ) ;val () = printLine ( IntInf.toString ( fact 120 ) ) ; |
| سحق |
$ mlton fact.sml $ ./fact 6689502913449127057588118054090372586752746333138029810295671352301 6335572449629893668741652719849813081576378932140905525344085894081 21859898481114389650005964960521256960000000000000000000000000000 |
تطبيق جزئي
تُستخدم الدوال المُطبّقة جزئيًا في العديد من التطبيقات، مثل التخلص من التعليمات البرمجية المُكررة. على سبيل المثال، قد تتطلب وحدة برمجية دوالًا من نوع معين ، ولكن من الأنسب كتابة دوال من نوع آخر حيث توجد علاقة ثابتة بين كائنات من النوع الأول والثاني . يمكن لدالة من النوع الأول استخراج هذه العلاقة المشتركة. هذا مثال على نمط المُهايئ .a->ba*c->bacc->(a*c->b)->a->b
في هذا المثال، يتم حساب المشتقة العددية لدالة معينة عند النقطة :fundfx
- دالة d delta f x = ( f ( x + delta ) - f ( x - delta )) / ( 2.0 * delta ) قيمة d = دالة : حقيقي -> ( حقيقي -> حقيقي ) -> حقيقي -> حقيقييشير نوع الدالة إلى أنها تُسقط قيمة عددية عشرية على دالة من النوع المحدد . يسمح لنا هذا بتطبيق الوسائط جزئيًا، وهو ما يُعرف بالتطبيق الجزئي . في هذه الحالة، يمكن تخصيص الدالة بتطبيق الوسيط المحدد جزئيًا عليها . يُعد الجذر التكعيبي لقيمة إبسيلون خيارًا مناسبًا عند استخدام هذه الخوارزمية .fund(real->real)->real->realddeltadelta
- val d' = d 1E~8 ; val d' = fn : ( real -> real ) -> real -> realيشير النوع المُستنتج إلى أن d'الدالة تتوقع دالة يكون نوعها هو وسيطها الأول. يمكننا حساب تقريب لمشتقةreal->realفيالإجابة الصحيحة هي.
- d' ( fn x => x * x * x - x - 1.0 ) 3.0 ; val it = 25.9999996644 : realالمكتبات
معيار
تم توحيد مكتبة Basis [ 8 ] وتأتي مع معظم التطبيقات. وهي توفر وحدات للأشجار والمصفوفات وهياكل البيانات الأخرى، بالإضافة إلى واجهات الإدخال/الإخراج وواجهات النظام.
طرف ثالث
بالنسبة للحوسبة العددية ، توجد وحدة Matrix (لكنها معطلة حاليًا)، https://www.cs.cmu.edu/afs/cs/project/pscico/pscico/src/matrix/README.html .
فيما يخص الرسومات، تُعدّ cairo-sml واجهة مفتوحة المصدر لمكتبة Cairo للرسومات. أما في مجال التعلّم الآلي، فتوجد مكتبة خاصة بالنماذج الرسومية.
التطبيقات
تتضمن تطبيقات لغة التعلم الآلي القياسية ما يلي:
معيار
- HaMLet : مترجم لغة ML القياسي الذي يهدف إلى أن يكون تطبيقًا مرجعيًا دقيقًا وسهل الوصول إليه للمعيار
- MLton ( mlton.org ): مُصرّف مُحسِّن للبرنامج بأكمله ، يلتزم التزامًا صارمًا بالتعريف، ويُنتج شفرة سريعة جدًا مقارنةً بتطبيقات ML الأخرى، بما في ذلك الواجهات الخلفية لـ LLVM وC.
- موسكو إم إل : تطبيق خفيف الوزن، يعتمد على محرك وقت التشغيل Caml Light الذي يُنفذ لغة Standard ML بالكامل، بما في ذلك الوحدات النمطية وجزء كبير من المكتبة الأساسية.
- Poly/ML : تطبيق كامل لـ Standard ML ينتج رمزًا سريعًا ويدعم الأجهزة متعددة النوى (عبر خيوط واجهة نظام التشغيل المحمولة ( POSIX ))؛ يقوم نظام التشغيل الخاص به بجمع القمامة بالتوازي والمشاركة عبر الإنترنت للهياكل الفرعية غير القابلة للتغيير.
- لغة التعلّم الآلي القياسية لولاية نيوجيرسي ( smlnj.org ): مُصرّف كامل، مع مكتبات وأدوات مُصاحبة، وواجهة تفاعلية، ووثائق تدعم التعلّم الآلي المتزامن.
- SML.NET : مُصرّف لغة ML قياسي لبيئة تشغيل اللغة المشتركة مع ملحقات للربط مع أكواد إطار عمل .NET الأخرى
- مجموعة أدوات التعلم الآلي (ML Kit) مؤرشفة بتاريخ 7 يناير 2016 على موقع Wayback Machine : تطبيق يعتمد بشكل وثيق على التعريف، ويتضمن جامعًا للبيانات المهملة (يمكن تعطيله) وإدارة ذاكرة قائمة على المناطق مع استنتاج تلقائي للمناطق، بهدف دعم التطبيقات في الوقت الفعلي.
المشتق
- أليس : مترجم للغة Standard ML من جامعة سارلاند، يدعم البرمجة المتوازية باستخدام المستقبلات ، والتقييم الكسول ، والحوسبة الموزعة عبر استدعاءات الإجراءات عن بُعد ، وبرمجة القيود.
- SML# : امتداد لـ SML يوفر تعدد أشكال السجلات والتوافق مع لغة C. وهو مُصرّف أصلي تقليدي، واسمه لا يُشير إلى تشغيله على إطار عمل .NET.
- SOSML : تطبيق مكتوب بلغة TypeScript ، يدعم معظم لغة SML وأجزاء مختارة من المكتبة الأساسية
بحث
- CakeML هي نسخة REPL من ML مع وقت تشغيل تم التحقق منه رسميًا وترجمة إلى لغة التجميع.
- تدمج إيزابيل ( Isabelle/ML، مؤرشفة بتاريخ 30 أغسطس 2020 على موقع Wayback Machine ) لغة Poly/ML المتوازية في مُثبت نظريات تفاعلي، مع بيئة تطوير متكاملة متطورة (مبنية على jEdit ) للغة Standard ML الرسمية (SML'97)، ولهجة إيزابيل/ML، ولغة البرهان. بدءًا من إصدار إيزابيل 2016، يتوفر أيضًا مصحح أخطاء على مستوى الكود المصدري للغة ML.
- يقوم Poplog بتنفيذ نسخة من Standard ML، إلى جانب Common Lisp و Prolog ، مما يسمح ببرمجة اللغات المختلطة؛ يتم تنفيذ كل ذلك في POP-11 ، والذي يتم تجميعه بشكل تدريجي .
- TILT هو مترجم معتمد بالكامل للغة Standard ML التي تستخدم لغات وسيطة مكتوبة لتحسين التعليمات البرمجية وضمان صحتها، ويمكنه الترجمة إلى لغة تجميع مكتوبة .
جميع هذه التطبيقات مفتوحة المصدر ومتاحة مجانًا. معظمها مُنفذ بلغة Standard ML. لم تعد هناك تطبيقات تجارية؛ فقد أنتجت شركة Harlequin ، التي توقفت عن العمل الآن، بيئة تطوير متكاملة ومترجمًا تجاريًا يُسمى MLWorks، والذي انتقل إلى Xanalys، ثم أصبح مفتوح المصدر بعد استحواذ شركة Ravenbrook Limited عليه في 26 أبريل 2013.
مشاريع كبرى تستخدم لغة SML
تم تنفيذ بنية المؤسسة الكاملة لجامعة كوبنهاغن لتكنولوجيا المعلومات في حوالي 100000 سطر من لغة SML، بما في ذلك سجلات الموظفين، وكشوف المرتبات، وإدارة الدورات التدريبية والتقييم، وإدارة مشاريع الطلاب، وواجهات الخدمة الذاتية المستندة إلى الويب. [ 9 ]
تمت كتابة برامج المساعدة في البرهان HOL4 و Isabelle و LEGO و Twelf بلغة Standard ML. كما يستخدمها مطورو المترجمات ومصممو الدوائر المتكاملة مثل ARM . [ 10 ]
انظر أيضاً
مراجع
- ↑ هاربر، روبرت (5 مايو 1998). "البرمجة بلغة Standard ML" (ملف PDF) . مؤرشف من الأصل (ملف PDF) في 30 ديسمبر 2025. تم الاطلاع عليه في 30 ديسمبر 2025 .
- 1 2 "SML '97" . www.smlnj.org .
- ↑ "itertools — دوال لإنشاء مكررات من أجل التكرار الفعال — وثائق بايثون 3.7.1rc1" . docs.python.org .
- ↑ "التأثيرات - مرجع الصدأ" . مرجع الصدأ . تم الاسترجاع في 31 ديسمبر 2023 .
- ^ ميلنر، روبن ؛ توفت, مادس ; هاربر، روبرت (1990). تعريف المعيار ML (PDF) . كامبريدج، ماساتشوستس: مطبعة معهد ماساتشوستس للتكنولوجيا. رقم ISBN 978-0-262-13255-8تمت أرشفة هذا الملف من النسخة الأصلية (PDF) في 8 أكتوبر 2025.
- ^ ميلنر، روبن. توفت، مادس؛ هاربر، روبرت. ماكوين، ديفيد (1997). تعريف معيار ML (المنقح) (PDF) . مطبعة معهد ماساتشوستس للتكنولوجيا. رقم ISBN 978-0-262-63181-5تمت أرشفة هذا الملف من النسخة الأصلية (PDF) في 23 نوفمبر 2025.
- ↑ أوكاساكي، كريس (1 سبتمبر 2000). "الترقيم بالعرض أولاً: دروس مستفادة من تمرين بسيط في تصميم الخوارزميات" . ACM SIGPLAN Notices . 35 (9): 131–136 . doi : 10.1145/357766.351253 . ISSN 0362-1340 .
- ↑ "مكتبة أساسيات التعلم الآلي القياسية" . smlfamily.github.io . تم الاطلاع عليه بتاريخ 10 يناير 2022 .
- ↑ توفت، مادز (2009). "لغة ML القياسية" . موسوعة سكولاربيديا . 4 (2): 7515. رمز Bibcode : 2009SchpJ...4.7515T . doi : 10.4249/scholarpedia.7515 .
- ↑ ألجلاف، جايد ؛ فوكس، أنتوني سي جيه؛ اشتياق، سامين؛ ميرين، ماغنوس أو؛ ساركار، سوسميت؛ سيويل، بيتر؛ نارديللي، فرانشيسكو زابا (2009). دلالات لغة برمجة Power و ARM Multiprocessor Machine Code (ملف PDF) . DAMP 2009. الصفحات 13-24 . doi : 10.1145/1481839.1481842 . مؤرشف (ملف PDF) من النسخة الأصلية بتاريخ 14 أغسطس 2017.
روابط خارجية
حول لغة البرمجة القياسية ML
- التعريف المنقح
- مشروع Standard ML Family على GitHub، مؤرشف بتاريخ 20 فبراير 2020 في Wayback Machine
- ما هو SML؟
- ما هو SML '97؟
حول خليفة ML
- التعلم الآلي اللاحق (sML) : تطور التعلم الآلي باستخدام التعلم الآلي القياسي كنقطة انطلاق
- HaMLet على GitHub : تطبيق مرجعي لـ ML اللاحق
عملي
- برنامج تعليمي تمهيدي أساسي
- أمثلة في برنامج Rosetta Code
أكاديمي
- لغات البرمجة عالية المستوى
- اللغات الوظيفية
- لغات البرمجة الإجرائية
- عائلة لغات البرمجة ML
- لغات البرمجة التي تم إنشاؤها عام 1983
