22

我不明白 F# 中的值限制是如何工作的。我已经阅读了wiki以及MSDN 文档中的解释。我不明白的是:

  1. 为什么,例如,这给了我一个价值限制错误(取自这个问题):

    let toleq (e:float<_>) a b = (abs ( a - b ) ) < e
    

    但是这不是:

    let toleq e (a:float<_>) b = (abs ( a - b ) ) < e
    
  2. 这可以概括...

    let is_bigger a b = a < b
    

    但这不是(它被指定为 int):

    let add a b = a + b
    
  3. 为什么带有隐式参数的函数会产生值限制:

    这:

    let item_count = List.fold (fun acc _ -> 1 + acc) 0
    

    与这个:

    let item_count l = List.fold (fun acc _ -> 1 + acc) 0 l
    

    (请注意,如果我在代码片段中使用此函数,VR 错误将消失,但随后该函数将指定为我使用它的类型,并且我希望它被概括)

它是如何工作的?

(我使用的是最新的 F#,v1.9.6.16)

4

3 回答 3

20

编辑

更好/最近的信息在这里:保持部分应用的功能通用

(原文如下)

我认为务实的做法是不要试图深入理解这一点,而是要了解一些克服 VR 并继续工作的一般策略。这是一个“逃避”的答案,但我不确定在这里花时间了解 F# 类型系统的内部结构(从发布到发布继续以微小的方式变化)是否有意义。

我提倡的两个主要策略是这些。首先,如果你定义一个函数类型的值(类型带有箭头'->'),然后通过执行eta-conversion确保它是一个语法函数:

// function that looks like a value, problem
let tupleList = List.map (fun x -> x,x)
// make it a syntactic function by adding argument to both sides
let tupleList l = List.map (fun x -> x,x) l

其次,如果您仍然遇到 VR/泛化问题,则指定整个类型签名以说出您想要的内容(然后在 F# 允许的情况下“退出”):

// below has a problem...
let toleq (e:float<_>) a b = (abs ( a - b ) ) < e
// so be fully explicit, get it working...
let toleq<[<Measure>]'u> (e:float<'u>) (a:float<'u>) (b:float<'u>) : bool = 
    (abs ( a - b ) ) < e
// then can experiment with removing annotations one-by-one...
let toleq<[<Measure>]'u> e (a:float<'u>) b = (abs ( a - b ) ) < e

我认为这两种策略是最好的务实建议。也就是说,这是我试图回答您的具体问题的尝试。

  1. 我不知道。

  2. '>' 是一个完全通用的函数('a -> 'a -> bool),适用于所有类型,因此 is_bigger 可以泛化。另一方面,“+”是一个“内联”函数,它适用于少数原始类型和某一类其他类型;它只能在其他“内联”函数中泛化,否则必须将其固定为特定类型(或默认为“int”)。(即席多态的“内联”方法是 F# 中的数学运算符克服“类型类”不足的方法。)

  3. 这就是我上面讨论的“句法功能”问题;'让我们编译成字段/属性,与函数不同,它们不能是通用的。因此,如果您希望它具有通用性,请将其设为函数。(有关此规则的另一个例外情况,另请参阅此问题。)

于 2009-07-15T17:19:29.860 回答
5

引入值限制是为了解决存在副作用的多态性的一些问题。F# 从 OCaml 继承了这一点,我相信所有 ML 变体中都存在值限制。除了您引用的链接之外,还有一些 链接供您阅读。由于 Haskell 是纯的,因此不受此限制。

至于你的问题,我认为问题3确实与价值限制有关,而前两个则不是。

于 2009-07-17T03:55:54.037 回答
2

没有人,包括 F# 团队的人,以任何有意义的方式知道这个问题的答案。

F# 类型推理系统在编译器定义真理的意义上与 VB6 语法完全一样。

不幸的是,但事实如此。

于 2009-07-15T17:23:54.530 回答