【问题标题】:F# compiler complaining of invalid type in recursive functionF# 编译器在递归函数中抱怨无效类型
【发布时间】:2015-10-08 04:30:11
【问题描述】:

在 F# 中,我正在尝试编写一个函数,给定两个字符串,它将返回第一个字符串中第二个字符串开头的所有索引。我的函数如下所示:

let allIndexOf (str:string) (c:string) =
    let rec inner (s:string) l =
        match (s.IndexOf(c), (s.IndexOf(c)+1) = s.Length) with
        | (-1, _) -> l
        | (x, true) -> x::l
        | (x, false) -> inner(s.Substring(x+1) x::l)
    inner str []

问题出在(x, false) -> inner(s.Substring(x+1) x::l) 行上,编译器说预期类型 int list 但得到了 int list -> int list。我在这里做错了什么?

在这种情况下,我想用字符串的其余部分(减去匹配的部分)调用 inner 以查找更多匹配项。

【问题讨论】:

  • 我不确定它是否会给出您期望的结果,因为只有原始字符串的子字符串的递归调用会“抵消”结果。例如,使用allIndexOf "foobar" "o" 将给出[0; 1] 1 是“foobar”中“o”的第一个索引(注意颠倒的结果 BTW),0 是 Substring
  • 无法编辑以前的评论,所以我会在这里添加我做了一个fiddle 来说明(有各种方法,因为我不知道是否递归是否强制)
  • @Sehnsucht 感谢您花时间指出这一点。证明 SO 社区有多棒。您的 Comprehension func 是正确的,但我刚刚尝试了另一个测试用例:“foobarmanhelloman”“man”,对于这种情况,它出现了 RecursionWithAccumulator 和 RecursionWithContinuation。应该是 [6, 14] 但后两个给出了答案 [6]
  • 感谢@Sehnsucht 在您的帮助下,我已经通过传入偏移量修复了原始函数,并将其添加到结果中dotnetfiddle.net/2JjfXr
  • 哦只是一个小错误,我应该使用 > 而不是 >= 进行 idx 检查(我已经编辑了代码)。作为旁注,现在您的代码是正确的,但是使用子字符串会产生不必要的开销(创建只需要循环的新字符串),但这是次要的。

标签: recursion f#


【解决方案1】:

您是否忘记了第一个参数和第二个参数之间的括号?

    | (x, false) -> inner (s.Substring(x+1)) (x::l)

【讨论】:

  • 谢谢,就是这样。我不明白你为什么需要在 (s.Substring(x+1)) 周围加上括号?
  • 因为它是一个单一的参数,如果你不放括号它可能会被解释为 arg1 = s.Substring 和 arg2= x+1
  • 好吧我明白了,我会认为通过放置 s.Substring(x+1) 很明显它是一个参数,因为你正在传递 s.Substring(x+1) 的结果.我想我的大脑仍然在命令模式下工作:)
  • 是的,别忘了这里有咖喱。像 s.Substring 这样的表达式可以很好地解释为部分应用函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 2020-08-29
  • 1970-01-01
相关资源
最近更新 更多