gpt4 book ai didi

f# - 带有类型注释的 List.reduce 部分应用程序给出错误 FS0030

转载 作者:行者123 更新时间:2023-12-03 09:55:06 26 4
gpt4 key购买 nike

let ones = List.map (fun _ -> 1)

不能一概而论,给出 FS0030 value error.

这可以通过类型注释来修复(以及其他方式):
let ones<'a> : 'a list -> int list = List.map (fun _ -> 1)

但是,在以下情况下:
let count = List.fold (fun t _ -> t + 1) 0

什么类型注解会起作用,或者,为什么添加类型注解对编译器没有帮助?
let count : 'a list -> int = List.fold (fun t _ -> t + 1) 0

(我知道 List.length,或者我可以使用 count x = x |> List.fold .. 等等,我想了解的是为什么类型注释适用于 List.map 示例,而不适用于 List.reduce )

最佳答案

简答

这是正确的语法:

let count<'a> : 'a list -> int = List.fold (fun t _ -> t + 1) 0

解释

帮助的不是类型注释,而是泛型参数。
这将编译(甚至可以工作):
let count<'a> = List.fold (fun t _ -> t + 1) 0

错误 FS0030 与编译器无法确定类型无关。这是关于你声明一个值(不是函数),其类型是通用的。由于过于复杂而无法在此描述的原因,不允许使用此类值。或者,更准确地说,它们是允许的,但前提是您通过显式指定泛型参数表明您知道自己在做什么。

然而,即使使用泛型参数,值的实际推断类型也可能不是您所期望的。例如,如果您将上述示例粘贴到 F# 代码编辑器中并将鼠标悬停在 count 上,你会发现它的类型是 obj list -> int .

奇怪的?更奇怪的是 - 在定义之后添加另一行:
let count<'a> = List.fold (fun t _ -> t + 1) 0
let c = count [1..5]

现在将鼠标悬停在 count - 它的类型变成了 int list -> int .

奇怪的?这里更陌生:-)
let count<'a> = List.fold (fun t _ -> t + 1) 0
let c = count [1..5]
let c2 = count ["a"; "b"; "c"]

现在第三行根本没有编译,提示“a”、“b”和“c”应该是 int .

跆拳道?
这是 F# 的一个特性——推断“临时”最通用的类​​型,然后根据实际使用情况进行修复。这就是为什么要单独使用 count变成 obj list -> int ( obj 是最终的父类(super class)型),但是一旦您将它与 int list 一起使用,编译器将类型固定为 int list -> int反而。如果您尝试将它与 string list 一起使用之后,它将无法编译,这是可以理解的。

使用多态算术运算符可以观察到相同的效果:
let add x y = x + y
add 2.0 4.5
add "a" "b"

隔离的第一行推断 int -> int -> int ,但只要添加第二行,类型 add变成 float -> float -> float (基于使用情况),然后第三行失败是可以理解的。

这种情况可以通过指定您想要的确切类型来解决:
let count<'a> : 'a list -> int = List.fold (fun t _ -> t + 1) 0

现在 count将是一个真正的通用函数。

关于f# - 带有类型注释的 List.reduce 部分应用程序给出错误 FS0030,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38212828/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com