2016-07-27 62 views
7

位置泛型类型的错误,我创建了一个基于Enumerable.OfType<'T>()的序列的管道能够ofType<'T>功能:与视功能

let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>() 

.fsx文件中使用也能正常工作;它仍然没有当我把它变成一个模块:

module Seq = 
    let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>() 

它停止工作,当我移动到另一个脚本文件,(要能够从其他地方访问它)在另一个顶层模块把它包:

module Prelude = 
    open System.Linq 

    module Seq = 
     let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>() 

我引用这个从我原来的脚本文件,打开Prelude模块,并调用这样的功能:

let getXmlIncludes (xtype : Type) = 
    xtype.GetCustomAttributes() |> Seq.ofType<XmlIncludeAttribute> 

这导致Seq.ofType<XmlIncludeAttribute>是坊间d为错误,用消息

error FS0001: Type mismatch. Expecting a 
    Collections.Generic.IEnumerable<Attribute> -> 'a  
> but given a 
    Collections.Generic.IEnumerable<Attribute> -> Collections.Generic.IEnumerable<XmlIncludeAttribute>  
The type 'obj' does not match the type 'Attribute' 

误差保持不变时,我直接移动ofType<'T>Prelude模块。

为什么会发生这种情况,我该如何让它不发生?

(我试图改变_ seq类型为sequence参数'TSeq seq,导致广受欢迎的

warning FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'TSeq has been constrained to be type 'obj'. 

,但并不会改变对错误的东西)

+0

我似乎无法重现你的错误。也许你可以提供一个显示错误的回购。 – Ringil

+1

现在的'Seq.cast'已经变成了一个'Enumerable.OfType'了吗? – Sehnsucht

+1

@Sehnsucht'OfType '与'.Where(x => x是typeof(T))'相同。按类型过滤。按照我的答案中的第一个链接,您将在同一屏幕上看到“OfType”和“Cast”实现。 –

回答

7

Enumerable.OfType<'T>()not generic关于输入参数。将_ seq更改为非通用IEnumerable后,该错误消失。

open System 
open System.Collections 
open System.Reflection 
open System.Xml.Serialization 

module Prelude = 
    open System.Linq 
    module Seq = 
     let inline ofType<'T> (sequence : IEnumerable) = sequence.OfType<'T>() 

open Prelude 
let getXmlIncludes (xtype : Type) = 
    xtype.GetCustomAttributes() |> Seq.ofType<XmlIncludeAttribute> 

在你原来的代码(sequence : _ seq)被约束到seq<Attribute>,但F#doesnot支持类型的协方差,并且不能与seq<XmlIncludeAttribute>工作,如果它是seq<Attribute>,即使XmlIncludeAttribute继承Attribute。但即使F#支持协方差,您的示例只适用于此特定情况,仅适用于从Attribute继承的类型。

你可以清楚地看到错误,如果你尝试与不同类型的使用你的序列扩展:

let getIntsAsUints (list : List<int>) = 
    list |> Seq.ofType<uint32> 

Script.fsx(21,13): error FS0001: The type 'List<int>' is not compatible with the type 'seq<Attribute>' 
+0

谢谢; '.OfType <'T>()'在非泛型'IEnumerable'上工作是我忽略的东西。 – TeaDrivenDev