Методы расширения F # для списков, IEnumerable и т. Д. - PullRequest
0 голосов
/ 02 января 2011

В 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() ) }
    }  
}

Как мне добиться чего-то подобного с типом записи и коллекцией (List или Seq предпочтительно в F #).Я хотел бы иметь список Widgest и иметь возможность вызывать функцию прямо в коллекции, которая сделала что-то вроде этого.Предположим (так как это F #), что функция не будет изменять состояние коллекции, к которой она присоединена, а возвращает какое-то новое значение.

1 Ответ

4 голосов
/ 02 января 2011

Точно аналогичное решение невозможно в F #. Элементы расширения F # могут быть определены только так, как если бы они были членами исходного типа, поэтому вы можете определять расширения F # для универсального типа IEnumerable<'T>, но не для конкретных экземпляров, таких как IEnumerable<Widget>.

В 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
...