F# 隐式键入在简单递归上窒息
F# implicit typing choking on simple recursion
当我在 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
...一切都很好。当我试图这样避免 "empty list" 问题时:
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
...我被骂:
recursion.fsx(5,9): error FS0001: This expression was expected to have type
unit
but here has type
decimal
我在这里错过了什么?
来自 the docs:
The types of the values produced in each branch must match. If there is no explicit else
branch, its type is unit
. Therefore, if the type of the then
branch is any type other than unit
, there must be an else
branch with the same return type.
你没说 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
(N.b。我在这里使用了 elif
而不是嵌套另一个 if
表达式;希望这不会分散注意力。)
也就是说,您涉及 startState
的逻辑非常可疑;它始终为零,在这里真的没有用。您的状态可能应该是参数而不是本地值,因此它可以用作累加器:
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
最后,让我们让它变得地道:
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
可以缩短为
let recursiveSum inputs =
let rec impl state = function
| [] -> state
| h::t -> impl (state + h) t
impl 0.0m inputs
有了 ildjarns 的回答,我想我会建议 could/should 一路走下去...
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
(而且我从不记得左或右,所以... ;-)
当我在 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
...一切都很好。当我试图这样避免 "empty list" 问题时:
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
...我被骂:
recursion.fsx(5,9): error FS0001: This expression was expected to have type
unit
but here has type
decimal
我在这里错过了什么?
来自 the docs:
The types of the values produced in each branch must match. If there is no explicit
else
branch, its type isunit
. Therefore, if the type of thethen
branch is any type other thanunit
, there must be anelse
branch with the same return type.
你没说 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
(N.b。我在这里使用了 elif
而不是嵌套另一个 if
表达式;希望这不会分散注意力。)
也就是说,您涉及 startState
的逻辑非常可疑;它始终为零,在这里真的没有用。您的状态可能应该是参数而不是本地值,因此它可以用作累加器:
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
最后,让我们让它变得地道:
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
可以缩短为
let recursiveSum inputs =
let rec impl state = function
| [] -> state
| h::t -> impl (state + h) t
impl 0.0m inputs
有了 ildjarns 的回答,我想我会建议 could/should 一路走下去...
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
(而且我从不记得左或右,所以... ;-)