我ofType<'T>基于以下方式为序列创建了一个可管道的函数Enumerable.OfType<'T>():
let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>()
Run Code Online (Sandbox Code Playgroud)
在同一个.fsx文件中使用它可以正常工作; 我把它放入模块时仍然会这样做:
module Seq =
let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>()
Run Code Online (Sandbox Code Playgroud)
当我将其移动到另一个脚本文件中时(它能够从其他地方访问它)将它包装在另一个顶级模块中时它停止工作:
module Prelude =
open System.Linq
module Seq =
let ofType<'T> (sequence : _ seq) = sequence.OfType<'T>()
Run Code Online (Sandbox Code Playgroud)
我从原始脚本文件中引用它,打开Prelude模块并调用函数如下:
let getXmlIncludes (xtype : Type) =
xtype.GetCustomAttributes() |> Seq.ofType<XmlIncludeAttribute>
Run Code Online (Sandbox Code Playgroud)
这导致Seq.ofType<XmlIncludeAttribute>被标记为错误,带有消息
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'
Run Code Online (Sandbox Code Playgroud)
当我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'.
Run Code Online (Sandbox Code Playgroud)
但不会改变任何有关错误的内容.)
Enumerable.OfType<'T>()是不是通用至于输入参数.更改_ 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>
Run Code Online (Sandbox Code Playgroud)
在你原来的代码(sequence : _ seq)被约束seq<Attribute>,但F#并 不能支持型协方差和不能正常工作seq<XmlIncludeAttribute>,如果它是seq<Attribute>,即使XmlIncludeAttribute继承Attribute.但即使F#支持协方差,您的示例也只适用于此特定情况,仅适用于继承的类型Attribute.
如果您尝试使用不同类型的Seq扩展,则可以清楚地看到错误:
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>'
Run Code Online (Sandbox Code Playgroud)