F# - 处理类似地图的功能

pha*_*haz 5 f# functional-programming map

长话短说,我想出了这个有趣的函数集,它接受一个函数,f:'k - >'v,一个选择的值,k:'k,一个选择的结果,v:'v,用f作为基础对于一个新函数g:'k - >'v与f完全相同,除了它现在认为,gk = v.

这是为了实现它而编写的(非常简单的)F#代码:

let set : ('k -> 'v) -> 'k -> 'v -> 'k -> 'v = 
    fun f k v x ->
        if x = k then v else f x
Run Code Online (Sandbox Code Playgroud)

我的问题是:

这个功能有什么问题吗?

我可以想象重复使用这个功能,就像这样

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
Run Code Online (Sandbox Code Playgroud)

将开始在堆上构建一长串函数.这是值得关注的吗?

有没有更好的方法来做到这一点,同时仍然保持类型?

我的意思是,我可以做一些事情,比如构建一个用于保存原始函数的类型,f,一个Map,将键值对设置到地图,然后首先检查地图,第二个函数,当使用键获取值时,但这是这里没有什么让我感兴趣的 - 对于给定的函数,我感兴趣的是具有"修改"给定值的单个结果的功能.

Sør*_*ois 5

潜在问题:

  1. 该set如果重写相同值的两倍修饰功能泄漏空间:

    let huge_object = ...
    let small_object = ...
    
    let f0 = set f 0 huge_object
    let f1 = set f0 0 small_object
    
    Run Code Online (Sandbox Code Playgroud)

    即使它永远不能是输出f1,huge_object也不能进行垃圾收集,直到f1可以:huge_object被引用f0,而后者又被引用f1.

  2. 修改后的set函数在set应用于它的操作数上具有线性开销.

我不知道这些是否是您预期应用的实际问题.

如果你想set拥有完全相同的类型,('k -> 'v) -> 'k -> 'v -> 'k -> 'v那么我看不到更好的方式(*).显而易见的想法是拥有一个你已经修改过的函数的"修改表",然后在这个表中set查找一个给定的函数f.但是函数类型不允许进行相等性检查,因此您无法与f修改表中已知的函数集进行比较.

(*)反思不然.