我编写了一个应该接收元组列表的函数。我使用#
访问元组的组件,代码编译:
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
但另一个基本上做同样事情的函数,即接收元组列表并访问它们会导致错误。
fun validate ([]) = true
| validate (h::t) =
if 1 = (#1 h) then
true
else
false
Can't find a fixed record type. Found near #1
这里有什么区别,为什么后者会导致错误?
第一个函数实际上不能单独编译。
但整个片段确实如此:
fun drop ([], n) = []
| drop (h::t, 0) = h::t
| drop (h::t, n) =
drop(t, n-1)
fun sts_linear (y, n) =
if y < (Math.sqrt(n)+1.0) then
let
(* x^2 + y^2 = n => x = sqrt(n-y^2) *)
val x = Math.sqrt(n - (y * y));
val xr = Real.realRound(x);
in
if (abs(x - xr) < 0.000000001) then
[(Real.trunc xr, Real.trunc y)]@sts_linear (y+1.0, n)
else
(
[]@sts_linear (y+1.0, n)
)
end
else []
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
fun sts (n) =
(
let
val pairs = sts_linear(0.0, Real.fromInt n);
in
recheck(drop(pairs, Real.ceil( Real.fromInt (length(pairs))/2.0 ) ), n)
end
)
答案 0 :(得分:2)
你的第一个代码没有编译,至少使用SML / NJ:
如果你要编译它,那么它必须是SML的非标准扩展。
两个定义的问题在于SML中没有tuple
任意arity的多态概念。您可以编写函数来处理对列表。您可以编写函数来处理三元组列表。但是 - 你不能写函数同时在三元组和三元组列表上工作(至少如果你的函数试图用这些对/三元组作为元组做事)。
一种解决方案是摆脱#
并使用模式匹配来提取组件:
fun validate [] = true
| validate ((x,y)::t) =
if x = 1 then
true
else
false
但是,如果你真的想编写一个可以多态地应用于对列表或三元组列表(或四元组......)的函数,最简单的方法是表示对,三元组等。作为列表而不是元组。包含非指定大小列表的列表在SML中不是问题。
答案 1 :(得分:0)
尝试最大限度地减少这种情况,因为我在SML / NJ中看到了以下工作 我并不知道它实际上是编译器扩展
val p1 = {x=0, y=0};
val p2 = {x=1, y=1};
val p3 = {x=1, y=1, z=1};
从编译器错误的角度来看,存在一个笨拙的构造 没有多少语言有错误以这种方式工作, 因为该函数有效,但会产生类型错误 除非存在函数调用来解决 'record'的类型,因此要解决错误,必须添加更多代码。
fun getFoo(field) = fn record => field record;
没有以下实际调用getX 编译器无法确定记录的类型 其中ALL字段的完整类型信息 必须为编译器知道记录,而不仅仅是#x字段。
let val getX = getFoo(#x);
val x1 = getX(p1);
val x2 = getX(p2);
val x3 = getFoo(#x)(p3);
in () end;
而以下注释掉的代码段会因为类型而导致错误 p1和p3是不同的,所以不同的getFoo调用 是必需的
(*
let val getX = getFoo(#x);
val x1 = getX(p1);
val x3 = getX(p3);
in () end;
*)
以下内容不充分,因为它永远无法解析记录。
let val getX = getFoo(#x) in () end;