F# 价值限制的困境

F# 价值限制的困境,f#,transducer,F#,Transducer,我在F#中试验Clojure传感器的实现,很快就遇到了可怕的值限制错误 传感器的整个要点是可组合的。这是一些示例代码: type Reducer'b->'a)->'a->'c->'a 模块传感器= [] 让内联映射proj:Reducer如上所述,并在错误消息本身中,可以显式添加参数吗 let xform x = x |> map ... [<GeneralizableValue>] let xform<'t> : Reducer<'t, _,

我在F#中试验Clojure传感器的实现,很快就遇到了可怕的值限制错误

传感器的整个要点是可组合的。这是一些示例代码:

type Reducer'b->'a)->'a->'c->'a
模块传感器=
[]

让内联映射proj:Reducer如上所述,并在错误消息本身中,可以显式添加参数吗

let xform x = x |> map ...
   [<GeneralizableValue>]
   let xform<'t> : Reducer<'t, _, _> = map (fun i -> i + 9) >> map (fun a -> a * 5) >> map (fun s -> s + 1)

F#只在无点方法中表现得很好

那么显式注释
xform

let xform x = x |> map ...
   [<GeneralizableValue>]
   let xform<'t> : Reducer<'t, _, _> = map (fun i -> i + 9) >> map (fun a -> a * 5) >> map (fun s -> s + 1)
[]
让xform=map(乐趣i->i+9)>>map(乐趣a->a*5)>>map(乐趣s->s+1)

为什么用
[]
注释
映射
会影响
xform
是否受值限制?(在任何情况下,
map
都是可以概括的,因为它是由lambda定义的;而且我也看不出所有
内联的
都有什么意义)

如果您的要求是:

  • xform
    必须是泛型函数,但不能是显式注释的类型函数
  • xform
    由操作符的应用程序定义(
    (>>)
    (在本例中)
那你就不走运了
xform
的主体不是一个可概括的表达式(参见F#spec中的§14.7),因此值限制适用于此处

此外,我认为这是有道理的。假设值限制不适用,我们调整了
map
的定义:

let map proj : Reducer<_,_,_> =
    printfn "Map called!"
    fun xf result input ->
        xf result (proj input)

不幸的是,您必须先将每个操作符(如
(>>)
提升到减速器级别,然后才能使用它,但这至少适用于您的示例,因为
xform
不再是通用值,但是使用泛型方法的非泛型值。

如错误所示,仅向
xform
添加参数有什么错?i、 e.
让xform x=x |>映射…
Hmm,看来您已经达到了F类型推断的极限。这里还有一点分析:@ChristopherStevenson它看起来确实像..这是调用站点,这对我来说不是好的语法。我已经让它工作了,但它太难看了,无法强迫用户使用lib。想象一下,打电话给Seq.map时也要这么做。谢谢!我有一些类似的想法,但我真的很喜欢Clojure传感器的功能组合。每个人都知道函数的组成,引入新的操作符不是我想做的事情。假设
map
不会有副作用,这里的值限制是适当的,因为F#编译器不能证明它没有副作用?是的,在存在潜在副作用的情况下,像值限制这样的东西对于维护类型安全是必要的。F#编译器是否可以做更多的工作来证明没有副作用,以便放松值限制?理论上是肯定的,但实际上存在一些问题。首先,编译器应该做多少工作来验证它?这个问题是不可判定的,所以不管怎样,你都必须满足于某种启发。编译器应该只检查源代码,还是应该尝试验证从其他DLL导入的代码的IL纯度?那么著名的CLR内部函数呢?然后,您决定的任何内容都需要成为语言规范的一部分,并且对于用户来说,解释这些内容要比当前的值限制(非常简单)困难得多。