我正在写这个名为inner
的curried f#函数,该函数应该将2个列表作为参数并根据位置相乘,然后返回总和:
let rec inner xs =
let aux ys = function
| ([], ys) -> 0
| (xs, []) -> 0
| (x::xs, y::ys) -> (x*y) + inner xs ys
aux ys;;
inner [1;2;3] [4;5;6];;
在这种情况下,答案是32,因为1 * 4 + 2 * 5 + 3 * 6 = 32.并且它有效,但是有这样的信息:
错误FS0001:类型不匹配。期待着
'a list -> 'd
但是给了一个'b list * 'a list -> int
类型
不匹配'a list
与类型'b list * 'a list
老实说,在调用它以使其正常工作时,我不知道放在aux
旁边的内容。
答案 0 :(得分:2)
我不确定究竟是什么误解。我注意到三个奇怪的观点:
let aux ys = function ([], ys) ->
声明并立即重新声明,从而隐藏标识符ys
。请注意,aux
是一个带有两个curried参数的函数,其中第二个是2元组。我怀疑这是你的意图。
aux
函数以相当不寻常的方式缩进;通常,它应该得到另一个四个空格的缩进。编译器可能不会抱怨这一点,只是在模式匹配后退出范围,但它增加了对失败行应该做什么的困惑。
ys
未定义上次使用的位置。 (这可能与令人困惑的缩进有关吗?)
以下是两种写作方式:
不是尾递归
let rec inner xs ys =
match xs, ys with
| x::xt, y::yt -> x * y + inner xt yt
| _ -> 0
在此版本中,curried参数转换为元组并用于匹配表达式。 (由于最后的添加,这可能会导致大型输入列表的堆栈溢出。)
尾递归,辅助功能
let rec private aux acc = function
| x::xs, y::ys -> aux (acc + x * y) (xs, ys)
| _ -> acc
let inner xs ys = aux 0 (xs, ys)
这里,辅助函数有两个curried参数,其中第一个是累加器,第二个是保存两个列表的元组。 inner
成为一个包装器函数,它通过初始化零来剥离累加器 - 并将tupled参数转换为curried参数,这也是要求。 (由于递归调用的值是函数返回值,因此该函数支持尾递归编译。)
答案 1 :(得分:1)
定义后,您需要调用aux
函数。目前,您的inner
函数只是定义了它,并没有对它做任何事情。
在这种情况下,如果您将aux
函数定义为采用两个参数,我不确定您是否确实需要定义inner
:
let rec inner (tuple : int list * int list) =
match tuple with
| ([], ys) -> 0
| (xs, []) -> 0
| (x :: xtail, y :: ytail) -> x * y + inner (xtail, ytail)
inner ([1;2;3], [4;5;6]) // 32
如果您想保留咖喱表格,则以下内容应该有效。您需要在匹配中包含xs
,然后返回aux
(将包含第一个列表并期望第二个列表):
let rec inner xs =
let aux ys =
match xs, ys with
| ([], ys) -> 0
| (xs, []) -> 0
| (x::xs, y::ys) -> (x*y) + inner xs ys
aux
inner [1;2;3] [4;5;6];; // 32