长话短说,我想出了这个有趣的功能设置,它需要一个功能, f:'k - > 'v ,选择的值 k:'k ,选择的结果 v:'v ,使用f作为新函数的基础 g:'k - > 'v 与 f 完全相同,除了它现在认为 g k = v 。
这是为了实现它而编写的(非常简单的)F#代码:
let set : ('k -> 'v) -> 'k -> 'v -> 'k -> 'v =
fun f k v x ->
if x = k then v else f x
我的问题是:
此功能是否会造成任何问题?
我可以想象重复使用这个函数,比如这个
let kvs : (int * int) List = ... // A very long list of random int pairs.
List.fold (fun f (k,v) -> set f k v) id kvs
将开始在堆上构建一长串函数。这是值得关注的吗?
有没有更好的方法来做到这一点,同时仍保持类型?
我的意思是,我可以做一些事情,比如构建一个用于保存原始函数的类型, f ,一个Map,将键值对设置到地图,以及检查首先是地图,第二个是函数,当使用键来获取值时,但这并不是我感兴趣的东西 - 我感兴趣的是为给定的函数设置了一个“修改”给定值的单个结果的函数。
答案 0 :(得分:5)
潜在问题:
如果您重写两次相同的值,set
- 修改后的函数会泄漏空间:
let huge_object = ...
let small_object = ...
let f0 = set f 0 huge_object
let f1 = set f0 0 small_object
即使它永远不会是f1
的输出,但只有huge_object
才能对f1
进行垃圾回收:huge_object
引用f0
,然后由f1
引用。
set
- 修改后的函数在应用于set
的操作数中具有开销线性。
我不知道这些是否是您预期应用程序的实际问题。
如果您希望set
具有完全类型('k -> 'v) -> 'k -> 'v -> 'k -> 'v
,那么我看不到更好的方式(*)。显而易见的想法是拥有一个已经修改过的函数的“修改表”,然后让set
在此表中查找给定的f
。但是函数类型不允许进行等式检查,因此您无法将f
与修改表中已知的函数集进行比较。
(*)反思不能承受。