F#查询表达式 - 为什么我会收到此类型比较错误?

时间:2012-07-29 14:22:15

标签: f# f#-3.0

我有以下代码块:

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,为什么我会收到此错误?

1 个答案:

答案 0 :(得分:3)

我想说这是类型检查器的混乱行为。

如果事先不知道nums的类型(如您的示例所示),则类型检查器会在nums块中首先使用query,并将其推断为{{1 }}。由于F#List未实现IQueryable<'a>界面,因此IQueryable'a list之间的统一失败。

如果您在声明中指定IQueryable<'a>的类型为nums,则'a listnums的使用看起来像for n in nums do集合的正常使用。

那说你在使用错误的工具。查询表达式旨在用于处理外部数据源。序列表达式应该有助于内存中查询:

IEnumerable