【问题标题】:F# Extension Methods on Lists, IEnumerable, etc列表、IEnumerable 等上的 F# 扩展方法
【发布时间】:2011-06-02 13:11:26
【问题描述】:

在 C# 中,如果我有一个小部件定义,请说:

class widget
{
    public string PrettyName() { ... do stuff here }
}

并且我想允许轻松打印小部件列表,我可以这样做:

namespace ExtensionMethods
{
    public static PrintAll( this IEnumerable<Widget> widgets, TextWriter writer )
    {
        foreach(var w in widgets) { writer.WriteLine( w.PrettyName() ) }
    }  
}

我将如何使用记录类型和集合(最好在 F# 中使用 List 或 Seq)来完成类似的操作。我很想拥有一个 Widgest 列表,并且能够在执行此类操作的集合上调用一个函数。假设(因为它是 F#)该函数不会改变它所附加的集合的状态,而是返回一些新值。

【问题讨论】:

    标签: f# methods extension-methods static-methods c#-to-f#


    【解决方案1】:

    在 F# 中不可能有完全类似的解决方案。 F# 扩展成员只能定义为原始类型上的成员,因此您可以在泛型类型 IEnumerable&lt;'T&gt; 上定义 F# 扩展,但不能在 IEnumerable&lt;Widget&gt; 等特定实例上定义 F# 扩展。

    在 C# 中,扩展方法通常用于提供更流畅的编码风格(例如myWidgets.PrintAll(tw))。在 F# 中,您通常只需定义一个 let-bound 函数并使用管道运算符来实现类似的效果。例如:

    module Widget =
      let printAll (tw:TextWriter) s =
        for (w:Widget) in s do
          writer.WriteLine(w.PrettyName())
    
    open Widget
    let widgets = // generate a sequence of widgets somehow
    let tw = TextWriter()
    widgets |> printAll tw
    

    【讨论】:

    • 如何将 printAll 函数定义为 Widget Record 类型的成员,以便在上述场景中使用?
    • @flevine100 - 您通常将 printAll 定义为类型的成员,而是定义为模块中的 let-bound 函数。我已经编辑了我的答案以包含一个示例。
    • 谢谢! - 函数式编程绝对是一种不同的代码组织方式。
    猜你喜欢
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多