为什么 #i 获取元组中的元素在命令行上工作而不是程序?

Why does #i to get elements in tuples work on command line but not program?

我刚开始学习 SML。我想写一个函数从元组中获取第二个元素。看起来很简单,因为在命令行上我可以说

val a = (1, 2, 3);
#2 a;

那么这个功能是怎么来的...

fun second(x) =
    #2 x;

抛出这个异常

考虑到您还处于起步阶段,暂时可以满足您的需求:

fun second(x : int * int * int) = #2 x;

SML 是一种强类型语言,它能够在程序员省略任何显式类型时推断出任何语句的正确类型。 只有在没有歧义的情况下,授予程序员的让步才不必用勺子喂养编译器计数,并且再次关于任何编程语句的正确类型。当面临无限的可能性时,就像在描述的场景中一样,它会抛出一个 flex 记录错误,因此:

Error: unresolved flex record
   (can't tell what fields there are besides #2)

请注意,函数的类型不仅是该函数的 return 类型,它还是函数参数到所需 return 类型的映射,格式为 'a => 'b

在所描述的情况下,当您没有明确地向编译器输入元组的长度时,输入的范围可以从两个元素的元组到无限元素的元组。

函数的类型是否为 'a * 'b => 'b、'a * 'b * 'c => 'b 或 'a * 'b * 'c * 'd * .... * 'z => 'b 等类型? ?

当遇到这种歧义时,解释器因此要求您以一种或另一种方式明确地用勺子喂养所涉及的元组的长度。

现在请注意,上面提供的类型(int * int * int),其目的并不是要通知编译器我们正在处理一个整数元组。这里的目的是告诉编译器我们正在处理三个元素的元组。

另一种解决问题的方法是模式匹配,这是一种更好的方法,但可能尚未在您的课程中介绍:

fun second(x,y,z) = y;
second(a);

请注意,类型推断在这里没有歧义,因为它显然属于三个参数到一个元素的映射。

注意:您可能会在这里感到困惑,第二个需要三个参数,但在调用时,只提供一个参数 a。这超出了这个问题的范围,因此省略以保持答案尽可能相关。

另请查看: [99] unresolved flex record (can't tell what fields there are besides %)