[英]F# implicit typing choking on simple recursion
When I define a recursive function in F# thus: 当我在F#中定义递归函数时:
let rec recursiveSum inputs =
let startState = 0.0m
if List.length inputs = 1 then
startState + inputs.Head
else
let t = List.tail inputs
startState + inputs.Head + recursiveSum t
...all is good. ...一切都很好。 When I attempt to avoid the "empty list" problem thus:
因此,当我尝试避免出现“空列表”问题时:
let rec recursiveSum inputs =
let startState = 0.0m
**if List.isEmpty inputs then startState**
if List.length inputs = 1 then
startState + inputs.Head
else
let t = List.tail inputs
startState + inputs.Head + recursiveSum t
...I get yelled at: ...我大吼:
recursion.fsx(5,9): error FS0001: This expression was expected to have type
unit
but here has type
decimal
What am I missing here? 我在这里想念什么?
The types of the values produced in each branch must match.
每个分支中产生的值的类型必须匹配。 If there is no explicit
else
branch, its type isunit
.如果没有显式
else
分支,则其类型为unit
。 Therefore, if the type of thethen
branch is any type other thanunit
, there must be anelse
branch with the same return type.因此,如果
then
分支的类型是除unit
以外的任何类型,则必须存在一个具有相同返回类型的else
分支。
You're missing said else
. 你想念
else
。
let rec recursiveSum inputs =
let startState = 0.0m
if List.isEmpty inputs then 0.0m
elif List.length inputs = 1 then
startState + inputs.Head
else
let t = List.tail inputs
startState + inputs.Head + recursiveSum t
(Nb I've used elif
here rather than nesting another if
expression; hopefully that's not too much of a distraction.) (注:我在这里使用的是
elif
,而不是嵌套另一个if
表达式;希望这不会引起太多干扰。)
That said, your logic involving startState
is highly suspect; 就是说,您极有可能涉及
startState
的逻辑; it's always zero, and really serves no purpose here. 它始终为零,在这里实际上没有任何作用。 Your state should probably be a parameter rather than a local value so it can be used as an accumulator:
您的状态可能应该是参数而不是局部值,因此它可以用作累加器:
let recursiveSum inputs =
let rec impl state inputs =
if List.isEmpty inputs then state
elif List.length inputs = 1 then
state + inputs.Head
else
let t = List.tail inputs
impl (state + inputs.Head) t
impl 0.0m inputs
Lastly, let's make it idiomatic: 最后,让我们习惯用法:
let recursiveSum inputs =
let rec impl state inputs =
match inputs with
| [] -> state
| [h] -> state + h
| h::t -> impl (state + h) t
impl 0.0m inputs
which can be shortened to 可以缩短为
let recursiveSum inputs =
let rec impl state = function
| [] -> state
| h::t -> impl (state + h) t
impl 0.0m inputs
With ildjarns answer, I think I would suggest that one could/should go all the way... 有了ildjarns的回答,我想我建议一个人可以/应该一直走下去...
let rec fold f acc = function
| [] -> acc
| [x] -> f x acc
| h::t -> fold f (f h acc) t
let someDec = [0.1m; 0.2m]
let someStr = ["world"; "Hello "]
someDec
|> fold (+) 0.0m
someStr
|> fold (+) ""
let recursiveSum = fold (+) 0.0m
someDec
|> recursiveSum
let recursiveStrAdd = fold (+) ""
someStr
|> recursiveStrAdd
someDec
|> recursiveSum
(And I never remember left or right here, so... ;-) (而且我永远都不记得在这里的左或右,所以... ;-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.