SML/NJ - 模式匹配动态类型

发布于 2024-08-12 18:46:10 字数 195 浏览 2 评论 0原文

是否可以编写具有动态类型输入参数的函数? 我尝试过模式匹配,但显然它不能像这样工作。

我想做这样的事情:

fun firstStr (0,n:string) = n
  | firstStr (b:string,n:string) = if b>n then n else b;

谢谢。

Is it possible to write functions with dynamically typed input parameters?
I tried pattern matching, but apparently it does not work like this.

I wish to do something like this:

fun firstStr (0,n:string) = n
  | firstStr (b:string,n:string) = if b>n then n else b;

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

安穩 2024-08-19 18:46:11

StandardML 是一种严格的静态类型语言。因此,不能有一个函数在第一种情况下接受 int,在第二种情况下接受字符串。你得到的错误是

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)

如果你想要一种情况是字符串和一种情况是整数,你可以创建一种新类型,即“标记联合"(又名“可区分联合”),其设计目的是易于与模式匹配一​​起使用。它看起来像这样:

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 中比较两个字符串时,我看到了字典顺序(也称为字母顺序)比较。这就是你想要的吗?

StandardML is a strict, statically typed language. Therefore, you can't have a function which accepts an int in the first case and a string in the second. The error you get is

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)

If you want to have one case which is a string and one case which is an int, you can make a new type, a "tagged union" (aka "discriminated union"), which is designed to be easy to use with pattern matching. It would look like this:

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

Of course, you might want to find some more appropriate name for this Wrapper type, something that makes sense in the context of your programme. Also please note that the type annotation on n is not really necessary; it would be more idiomatic to write

fun firstStr(Int 0,    n) = n
  | firstStr(String b, n) = if b>n then n else b

Additionally, the compiler will tell you you have left a case uncovered: What if the first argument is an integer not equal to zero?

Finally, it's not really clear what you mean by the comparison b>n, what aspect of the two strings did you want to compare? I see that when I compare two strings in SML, I see a lexicographic (aka alphabetic) comparison. Is that what you wanted?

情话已封尘 2024-08-19 18:46:11

详细一点,假设你有两个参数,每个参数都可以是一个字符串或一个整数,如果你有两个字符串,你想要字典顺序上较小的字符串,如果你有一个字符串,你想要那个字符串,如果你有两个整数不能返回字符串。你做什么工作?返回 string option 类型的值(在 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 类型。

To elaborate a little bit, suppose you have two arguments, each of which could be a string or an integer, and if you have two strings you want the lexicographically smaller string, if you have one string you want that string, and if you have two integers you can't return a string. What do you do? Return a value of type string option (look up option, SOME, and NONE at 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

Function firstStr has type

string_or_int * string_or_int -> string option

The fastest way to becoming a proficient ML programmer is to learn to think about types first. If for example, what you really wanted was a function of type string option * string -> string, you wouldn't need to write it yourself; the builtin function getOpt does that. On the other hand, it sounds like you want string option * string -> string, so you can write

fun firstStr(SOME a, b) = if a < b then a else b
  | firstStr(NONE,   b) = b

and you dont' need a SOME value constructor or an option type on the result.

缱倦旧时光 2024-08-19 18:46:11

OCaml 中的多态变体具有更多动态属性你正在寻找。如果你愿意的话可以看一下,OCaml 和 SML 是非常接近的语言。

Polymorphic variants in OCaml have more of the dynamic property you are looking for. You can take a look if you want, OCaml and SML are very close languages.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文