Multiple Patterns in 1 case

僤鯓⒐⒋嵵緔 提交于 2019-12-30 23:22:30

问题


In SML, is it possible for you to have multiple patterns in one case statement?

For example, I have 4 arithmetic operators express in string, "+", "-", "*", "/" and I want to print "PLUS MINUS" of it is "+" or "-" and "MULT DIV" if it is "*" or "/".

TL;DR: Is there somewhere I can simplify the following to use less cases?

case str of
   "+" => print("PLUS MINUS")
 | "-" => print("PLUS MINUS")
 | "*" => print("MULT DIV")
 | "/" => print("MULT DIV")

回答1:


Given that you've tagged your question with the smlnj tag, then yes, SML/NJ supports this kind of patterns. They call it or-patterns and it looks like this:

case str of
  ("+" | "-") => print "PLUS MINUS"
| ("*" | "/") => print "MULT DIV"

Notice the parentheses.

The master branch of MLton supports it too, as part of their Successor ML effort, but you'll have to compile MLton yourself.

val str = "+"

val _ =
  case str of
    "+" | "-" => print "PLUS MINUS"
  | "*" | "/" => print "MULT DIV"

Note that MLton does not require parantheses. Now compile it using this command (unlike SML/NJ, you have to enable this feature explicitly in MLton):

mlton -default-ann 'allowOrPats true' or-patterns.sml



回答2:


In Standard ML, no. In other dialects of ML, such as OCaml, yes. You may in some cases consider splitting pattern matching up into separate cases/functions, or skip pattern matching in favor of a shorter catch-all expression, e.g.

if str = "+" orelse str = "-" then "PLUS MINUS" else
if str = "*" orelse str = "/" then "MULT DIV" else ...



回答3:


Expanding upon Ionuț's example, you can even use datatypes with other types in them, but their types (and identifier assignments) must match:

datatype mytype = COST as int | QUANTITY as int | PERSON as string | PET as string;

case item of
  (COST n|QUANTITY n) => print Int.toString n
  |(PERSON name|PET name) => print name

If the types or names don't match, it will get rejected:

case item of
  (COST n|PERSON n) => (* fails because COST is int and PERSON is string *)
  (COST n|QUANTITY q) => (* fails because the identifiers are different *)

And these patterns work in function definitions as well:

fun myfun (COST n|QUANTITY n) = print Int.toString n
   |myfun (PERSON name|PET name) = print name
;


来源:https://stackoverflow.com/questions/36347681/multiple-patterns-in-1-case

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!