使用用户定义的数据类型作为函数参数的类型

using user-defined datatype as a type for a function argument

我定义了以下数据类型:

datatype Arguments
  = IntPair of int * int
  | RealTriple of real * real * real
  | StringSingle of string;

datatype OutputArgs = IntNum of int | RealNum of real | Str of string;

我尝试创建一个函数 MultiFunc: Arguments -> OutputArgs:

fun MultiFunc(RealTriple (x, y, z)) : OutputArgs = RealNum ((x+y+z)/3.0)
  | MultiFunc(IntPair (x,y)) : OutputArgs = IntNum (x+y)
  | MultiFunc(StringSingle(s)) : OutputArgs = Str (implode(rev(explode(s))));

然而,当我调用 MultiFunc(1.0,2.0,3.0) 时,出现以下错误:

stdIn:588.1-588.23 Error: operator and operand don't agree [tycon mismatch]
  operator domain: Arguments
  operand:         real * real * real
  in expression:
    MultiFunc (1.0,2.0,3.0)

即由于某种原因,它无法将输入参数识别为 RealTriple.

您需要将您的三元组包装到相应的数据构造函数中,以向编译器解释您的意思是 Arguments 类型,而不仅仅是实数的三元组:

MultiFunc (RealTriple (1.0,2.0,3.0))
MultiFunc(1.0,2.0,3.0)

for some reason it doesn't recognize the input argument as being a RealTriple.

那是因为输入不是 RealTriple,而是实数的三元组 (real * real * real)。

试试看:

- MultiFunc (RealTriple (1.0, 2.0, 3.0));
> val it = RealNum 2.0 : OutputArgs

下面是我编写函数的方式:

fun multiFunc (RealTriple (x, y, z)) = RealNum ((x+y+z)/3.0)
  | multiFunc (IntPair (x,y)) = IntNum (x+y)
  | multiFunc (StringSingle s) = Str (implode (rev (explode s)))

通过让函数名以小写字母开头,我在视觉上将它们与 RealTriple 这样的值构造函数区分开来。我不写 : OutputArgs 而是让函数的类型被推断出来。我省略了多余的括号,如 StringSingle(s)explode(s):在许多编程语言中,函数调用 必须 有括号。在标准 ML 中,函数应用是通过将函数在左侧并置在右侧并用空格分隔来实现的。所以 f xfx 上被调用,而 (f x) y 是 "whatever f x returns, used as a function, on y."