我正在阅读 Expert F# book,我发现了这段代码
open System.Collections.Generic
let divideIntoEquivalenceClasses keyf seq =
// The dictionary to hold the equivalence classes
let dict = new Dictionary<'key,ResizeArray<'T>>()
// Build the groupings
seq |> Seq.iter (fun v ->
let key = keyf v
let ok,prev = dict.TryGetValue(key)
if ok then prev.Add(v)
else let prev = new ResizeArray<'T>()
dict.[key] <- prev
prev.Add(v))
dict |> Seq.map (fun group -> group.Key, Seq.readonly group.Value)
示例使用:
> divideIntoEquivalenceClasses (fun n -> n % 3) [ 0 .. 10 ];;
val it : seq<int * seq<int>>
= seq [(0, seq [0; 3; 6; 9]); (1, seq [1; 4; 7; 10]); (2, seq [2; 5; 8])]
首先对我来说这段代码真的很难看,即使这是安全的,它看起来更像命令式语言而不是函数式语言......特别是与clojure相比。但问题不在于这个......我在字典定义方面遇到了问题
当我输入这个:
let dict = new Dictionary<'key,ResizeArray<'T>>();;
我明白了:
pruebafs2a.fs(32,5): error FS0030: Value restriction. The value 'dict' has been inferred to have generic type
val dict : Dictionary<'_key,ResizeArray<'_T>> when '_key : equality
Either define 'dict' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
好吗?...
非常感谢
改进问题:
好的,我一直在阅读有关价值限制的信息,我发现了这些有用的信息
特别是,只有函数定义和简单的不可变数据表达式会被自动泛化
...好的..这解释了为什么
let dict = new Dictionary<'key,ResizeArray<'T>>();;
不起作用......并展示了 4 种不同的技术,尽管在我看来它们只能解决错误,但不是使用通用代码的解决方案:
技巧 1:将值限制为非泛型
let empties : int list [] = Array.create 100 []
技巧 3:必要时向泛型函数添加虚拟参数
let empties () = Array.create 100 []
let intEmpties : int list [] = empties()
技巧 4:在必要时添加显式类型参数(类似于 tec 3)
let emptyLists = Seq.init 100 (fun _ -> [])
> emptyLists<int>;;
val it : seq<int list> = seq [[]; []; []; []; ...]
----- 也是唯一让我使用真正的泛型代码的方法 ------ 技术 2:确保泛型函数具有显式参数
let mapFirst = List.map fst //doesn't work
let mapFirst inp = List.map fst inp
好的,在 4 种技术中的 3 种技术中,我需要先解决通用代码,然后才能使用它……现在……返回书本示例……当编译器知道 'key 和 'T 的值时
让 dict = new Dictionary<'key,ResizeArray<'T>>()
在范围内,代码对于 let key 是任何类型都是非常通用的,同样的情况发生在 'T
最大的虚拟问题是:
当我将代码包含在函数中时(技术 3):
let empties = Array.create 100 [] //doesn't work
let empties () = Array.create 100 []
val empties : unit -> 'a list []
I need define the type before begin use it
let intEmpties : int list [] = empties()
对我来说(诚然,我对静态类型语言有点笨)这不是真正的通用,因为当我使用它时它无法推断类型,我需要定义类型然后传递值(而不是基于传递的值)以其他方式定义类型而没有那么明确..
非常感谢..非常感谢任何帮助