3

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

我想做这样的事情:

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

谢谢你。

4

3 回答 3

10

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?

于 2009-11-26T21:02:43.130 回答
7

稍微详细一点,假设你有两个参数,每个参数可以是一个字符串或一个整数,如果你有两个字符串,你想要字典上更小的字符串,如果你有一个字符串,你想要那个字符串,如果你有两个整数不能返回字符串。你做什么工作?返回类型的值(在http://www.standardml.org/Basis/option.htmlstring option查找optionSOME和):NONE

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 程序员的最快方法是先学会思考类型。例如,如果你真正想要的是 type 的函数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结果类型。

于 2009-11-27T22:36:24.247 回答
1

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

于 2009-11-27T21:11:39.683 回答