F# 价值限制的困境
我在F#中试验Clojure传感器的实现,很快就遇到了可怕的值限制错误 传感器的整个要点是可组合的。这是一些示例代码: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, _,
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内部函数呢?然后,您决定的任何内容都需要成为语言规范的一部分,并且对于用户来说,解释这些内容要比当前的值限制(非常简单)困难得多。