SML/NJ - مطابقة النمط للكتابة الديناميكية
-
05-07-2019 - |
سؤال
هل من الممكن كتابة وظائف باستخدام معلمات الإدخال المكتوبة ديناميكيًا؟لقد حاولت مطابقة الأنماط، ولكن يبدو أنها لا تعمل بهذه الطريقة.
أرغب في القيام بشيء مثل هذا:
fun firstStr (0,n:string) = n
| firstStr (b:string,n:string) = if b>n then n else b;
شكرًا لك.
المحلول
وStandardML هو صارمة، لغة كتابتها بشكل ثابت. لذلك، لا يمكن أن يكون لها وظيفة التي تقبل عدد صحيح في الحالة الأولى وسلسلة في الثانية. الخطأ الذي تحصل عليه هو
this clause: string * string -> 'Z
previous clauses: int * string -> 'Z
in declaration:
firstStr =
(fn (0,<pat> : string) => n
| (<pat> : string,<pat> : string) => if <exp> > <exp> then n else b)
إذا كنت تريد أن يكون حالة واحدة وهي سلسلة وحالة واحدة وهو عدد صحيح، يمكنك تقديم نوع جديد، وهو "<لأ href =" http://en.wikipedia.org/wiki/Tagged_union " يختلط = "noreferrer"> الكلمات الدلالية اتحاد "(المعروف أيضا باسم" التمييز الاتحاد ")، الذي تم تصميمه ليكون سهل الاستخدام مع نمط مطابقة. انها تبدو مثل هذا:
datatype Wrapper = Int of int
| String of string
fun firstStr(Int 0, n:string) = n
| firstStr(String b, n:string) = if b>n then n else b
وبطبيعة الحال، قد ترغب في العثور على بعض الاسم الأنسب لهذا النوع التفاف، وهو الأمر الذي من المنطقي في سياق البرنامج. كما يرجى ملاحظة أن هذا الشرح نوع على n
ليس من الضروري حقا. فإنه سيكون أكثر اصطلاحي لكتابة
fun firstStr(Int 0, n) = n
| firstStr(String b, n) = if b>n then n else b
وبالإضافة إلى ذلك، فإن المترجم اقول لكم كنت قد تركت حالة كشف: ما إذا كانت الوسيطة الأولى هو عدد صحيح لا تساوي الصفر
وأخيرا، فإنه ليس واضحا حقا ما تعنيه من b>n
المقارنة، ما الجانب من السلسلتين هل تريد المقارنة؟ أرى أنه عندما أقارن سلسلتين في SML، أرى lexicographic (أبجدية الملقب) المقارنة. هل هذا ما تريد؟
نصائح أخرى
للتوضيح قليلاً، لنفترض أن لديك وسيطتين، كل منهما يمكن أن تكون سلسلة أو عددًا صحيحًا، وإذا كان لديك سلسلتين فأنت تريد سلسلة أصغر معجميًا، وإذا كان لديك سلسلة واحدة فأنت تريد تلك السلسلة، وإذا كان لديك عددين صحيحين لا يمكنك إرجاع سلسلة.ماذا تفعل؟إرجاع قيمة النوع string option
(ابحث عن option
, SOME
, ، و NONE
في http://www.standardml.org/Basis/option.html):
datatype string_or_int = String of string
| Int of int
fun firstStr(String a, String b) = SOME (if a < b then a else b)
| firstStr(String a, Int _ ) = SOME a
| firstStr(Int _, String b) = SOME b
| firstStr(Int _, Int _ ) = NONE
وظيفة firstStr
لديه نوع
string_or_int * string_or_int -> string option
أسرع طريقة لتصبح مبرمجًا ماهرًا في ML هي أن تفعل ذلك تعلم كيفية التفكير في الأنواع أولاً.على سبيل المثال، ما تريده حقًا هو وظيفة من النوع string option * string -> string
, لن تحتاج إلى كتابتها بنفسك؛الوظيفة المضمنة getOpt
يفعل ذلك.ومن ناحية أخرى، يبدو وكأنك تريد string option * string -> string
, ، حتى تتمكن من الكتابة
fun firstStr(SOME a, b) = if a < b then a else b
| firstStr(NONE, b) = b
وأنت لا تحتاج إلى SOME
منشئ القيمة أو option
اكتب على النتيجة.
تعدد الأشكال المتغيرات في لغة كامل الموضوعية لديها أكثر من الملكية ديناميكية كنت تبحث عنه. يمكنك إلقاء نظرة إذا كنت تريد، لغة كامل الموضوعية وSML لغات ثيقة للغاية.