我有以下代码块:
let rec Sieve p nums =
let filtered = query { for n in nums do
where (n % p = 0 && n <> p)
select n } |> Seq.toList
if filtered = nums then filtered // Error
else
let nextIndex = 1 + (filtered |> List.findIndex (fun x -> x = p))
if nextIndex > filtered.Length then filtered
else
let next = filtered.[nextIndex]
Sieve next filtered
当我编译它时,我得到'类型''列表'与'System.Linq.IQueryable&lt;'a&gt; '不兼容。在我用注释错误标记的行上。
我发现如果我在Sieve中添加一个类型注释来为num创建它(nums:int list),那么它将正常工作。但是,如果我在行上替换nums
if filtered = nums then filtered
使用:
if filtered = [1..10] then filtered
然后我得到同样的错误,指的是在线上过滤:
Sieve next filtered
因为我在使用它之前将其直接转换为List,为什么我会收到此错误?
答案 0 :(得分:3)
我想说这是类型检查器的混乱行为。
如果事先不知道nums
的类型(如您的示例所示),则类型检查器会在nums
块中首先使用query
,并将其推断为{{1 }}。由于F#List未实现IQueryable<'a>
界面,因此IQueryable
和'a list
之间的统一失败。
如果您在声明中指定IQueryable<'a>
的类型为nums
,则'a list
中nums
的使用看起来像for n in nums do
集合的正常使用。
那说你在使用错误的工具。查询表达式旨在用于处理外部数据源。序列表达式应该有助于内存中查询:
IEnumerable