这个F#curried函数有什么问题?
我正在编写一个名为这个F#curried函数有什么问题?,f#,functional-programming,F#,Functional Programming,我正在编写一个名为internal的通用f#函数,该函数应将两个列表作为参数,并根据位置将两者相乘,然后返回总和: 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,因为
internal
的通用f#函数,该函数应将两个列表作为参数,并根据位置将两者相乘,然后返回总和:
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列表
与类型'b列表*'a列表
老实说,我不知道在调用
aux
使其工作时,应该在它旁边放什么。在定义了aux
函数后,需要调用它。目前,您的内部函数只定义了它,而不使用它
在这种情况下,如果将内部
函数定义为接受两个参数,我不确定您是否真的需要定义aux
:
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
(这将包含第一个列表,并且需要第二个列表):
定义后需要调用aux
函数。目前,您的内部函数只定义了它,而不使用它
在这种情况下,如果将内部
函数定义为接受两个参数,我不确定您是否真的需要定义aux
:
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
(这将包含第一个列表,并且需要第二个列表):
定义后需要调用aux
函数。目前,您的内部函数只定义了它,而不使用它
在这种情况下,如果将内部
函数定义为接受两个参数,我不确定您是否真的需要定义aux
:
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
(这将包含第一个列表,并且需要第二个列表):
定义后需要调用aux
函数。目前,您的内部函数只定义了它,而不使用它
在这种情况下,如果将内部
函数定义为接受两个参数,我不确定您是否真的需要定义aux
:
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
(这将包含第一个列表,并且需要第二个列表):
我不确定到底是什么误解。我注意到三个奇怪的点:
让aux ys=function([],ys)->
声明并立即重新声明标识符,从而隐藏标识符ys
。请注意,aux
是一个具有两个常用参数的函数,其中第二个参数是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参数,第一个是累加器,第二个是保存两个列表的元组internal
变成了一个包装函数,它通过初始化累加器来剥离累加器,并将元组参数转换为curried参数,就像需求一样。(由于递归调用的值是函数的返回值,因此此函数支持尾部递归编译。)我不确定到底是什么误解。我注意到三个奇怪的点:
让aux ys=function([],ys)->
声明并立即重新声明标识符,从而隐藏标识符ys
。请注意,aux
是一个具有两个常用参数的函数,其中第二个参数是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参数,第一个是累加器,第二个是保存两个列表的元组internal
成为一个包装函数,它通过使用零初始化累加器来剥离累加器,并将元组参数转换为curry参数