SML/NJ - 模式匹配动态打字

Art*_*ium 3 functional-programming sml smlnj

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

我希望做这样的事情:

fun firstStr (0,n:string) = n
  | firstStr (b:string,n:string) = if b>n then n else b;
Run Code Online (Sandbox Code Playgroud)

谢谢.

har*_*rms 10

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)
Run Code Online (Sandbox Code Playgroud)

如果你想要一个字符串是一个字符串而一个是一个int的case,你可以创建一个新类型,一个" 标记联合 "(又名"识别联合"),它被设计成易于使用模式匹配.它看起来像这样:

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
Run Code Online (Sandbox Code Playgroud)

当然,您可能希望为此Wrapper类型找到一些更合适的名称,这在程序的上下文中是有意义的.另请注意,类型注释n并非真正必要; 写作会更加惯用

fun firstStr(Int 0,    n) = n
  | firstStr(String b, n) = if b>n then n else b
Run Code Online (Sandbox Code Playgroud)

另外,编译器会告诉你你已经发现了一个案例:如果第一个参数是一个不等于零的整数怎么办?

最后,通过比较你的意思并不是很清楚b>n,你想要比较两个字符串的哪个方面?我看到当我比较SML中的两个字符串时,我看到了一个词典(又称字母)比较.那是你想要的吗?


Nor*_*sey 7

稍微说一下,假设你有两个参数,每个参数可以是一个字符串或一个整数,如果你有两个字符串你想要字典缩小字符串,如果你有一个字符串你想要那个字符串,如果你有两个整数你不能返回一个字符串.你是做什么?返回类型的值string option(查找option,SOME以及NONEhttp://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
Run Code Online (Sandbox Code Playgroud)

功能firstStr有类型

string_or_int * string_or_int -> string option
Run Code Online (Sandbox Code Playgroud)

成为精通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
Run Code Online (Sandbox Code Playgroud)

并且你不需要SOME值结构的值构造函数或option类型.