我只是在学习f#所以我可能正在做一些非常愚蠢的事情。请随意指出我的相关文档,我已经搜索但无法找到。我在Windows 7(.Net 4.0)上使用Visual Studio 2010 beta。
我的第一个f#项目一切顺利。嗯..几乎一切。特别是 我正在编写一个非常简单的线性插值函数,其代码如下:
let linterp (x:double) (xvalues:double list) (yvalues:double list) =
let num_els = xvalues.Length
if x <= xvalues.Head then
let result = yvalues.Head
elif x >= (List.rev xvalues).Head then
let result = (List.rev yvalues).Head
else for idx in [0 .. num_els] do
if List.nth xvalues idx >= x then
let x0 = xvalues.Item idx
let y0 = yvalues.Item idx
let x1 = xvalues.Item (idx+1)
let y1 = yvalues.Item (idx+1)
let result = y0 + (y1-y0)/(x1-x0)*(x - x0)
result
我收到一系列错误,完全无法理解。
这是错误和警告的列表:
“这个'let'的返回表达式中的错误。第一个,第二个和最后一个”let“可能是正确的缩进。
“可能不正确的缩进:此标记在位置(39:10)处开始的上下文越位。请尝试进一步缩进此标记或使用标准格式约定”for“if”
“表达式中此点或之前的不完整结构化构造”,用于最后一行(结果)。
我将补充一点,我不得不冒汗来注释类型,因为由于某些原因我不知道编译器能够正确推断出第一个列表,但是对于第二个类型总是推断为单位此外,我的原始版本没有绑定名称结果,只是“返回表达式”,就像在
中一样if x <= xvalues.Head then
yvalues.Head
或
else for idx in [0 .. num_els] do
if List.nth xvalues idx >= x then
let x0 = xvalues.Item idx
let y0 = yvalues.Item idx
let x1 = xvalues.Item (idx+1)
let y1 = yvalues.Item (idx+1)
y0 + (y1-y0)/(x1-x0)*(x - x0)
这会在“for”下留下一个错误,说“此表达式具有类型单位但在此处使用类型为double”,并且“if”可能错误地缩进。
我认为,当我看到解决方案时,我会感到愚蠢,但是我已经被困在这么简单的问题上超过一个小时,所以我在寻求你的帮助。
提前致谢!
ps:我已经检查过选项卡在工具 - >&gt;选项 - &gt; .... - &gt;中被正确解释为空格F# - &gt;标签菜单
pps:这是关于SO的第一个问题: - )
答案 0 :(得分:5)
您的问题就像是
let result = yvalues.Head
不是一个完整的表达式,因此它不能形成if
块的一个分支的主体。您的初始方法是正确的,除了for ... do
循环不返回有意义的值(它返回()
,这是类型unit
的唯一值,因为编译器正在尝试解释;这与C#等语言中的void
类似。而不是for
循环,您将需要使用具有您正在寻找的值的表达式。对代码的最小更改是使用您在循环中强制设置的可变值。更惯用的方法是使用像List.fold这样的内置函数将列表压缩为单个值。这很复杂,因为您需要访问列表中的连续条目(并且您需要同时对xvalues和yvalues进行操作),这意味着您可能需要使用List.zip和Seq.pairwise,这可能是降低不熟悉F#的人的清晰度。
此外,您还可以应用其他一些更改来使您的代码更加惯用。例如,let x0 = xvalues.Item idx
更常见的是let x0 = xvalues.[idx]
。但请注意,F#列表是不可变的链表,因此不支持快速随机访问。这是支持使用内置List
运算符的方法的另一个原因。
答案 1 :(得分:5)
let linterp x (xvalues:double list) (yvalues:double list) =
if x <= xvalues.Head then
yvalues.Head
elif x >= (List.rev xvalues).Head then
(List.rev yvalues).Head
else
let idx = List.findIndex (fun e -> e >= x) xvalues
let x0 = xvalues.Item idx
let y0 = yvalues.Item idx
let x1 = xvalues.Item (idx+1)
let y1 = yvalues.Item (idx+1)
y0 + (y1-y0)/(x1-x0)*(x - x0)