Есть ли уже встроенные функциональные конструкции C # / .NET, подобные этим?г (ч ()) или - PullRequest
10 голосов
/ 23 января 2012
public static Func<V> To<T, V>(this Func<T> g, Func<T, V> h)
{
    return () => h(g());
}

public static Func<T> ToIdentity<T>(this T t)
{
    return () => t;
}

Я иногда использую эти и другие при задержке оценки. Они уже есть в библиотеке .net?

Edit:

Вот пример использования:

public static string SuffixColumn(this string v, string suffix, int columns)
{
    return
    v.ToIdentity()
        .ToScrubbedHtml()
        .ToFormat(() => "{0} " + suffix.ToLower().PadLeft(columns, ' '))
        .ToErrorText(v, suffix, columns)();
}

ToErrorText проверяет 'v' как легитимное (без кода ошибки, не ноль и т. Д.), Если хорошо, он запускает цепочку в Func, если плохо, он дает отказоустойчивый текстовый результат. Если v, суффикс или столбцы не годятся, ToFormat никогда не будет вызван. (Отсюда отсроченное / не оцененное использование).

ToFormat является почти составом предоставленного Func и string.Format. ToIdentity используется для поднятия v к Func, а затем все в цепочке основано на некотором Func из T.

Ответы [ 2 ]

34 голосов
/ 24 января 2012

Дайте мне посмотреть, понимаю ли я: вы используете лямбда-выражения для захвата значений в объекте-обертке - Func<T> - и затем строите рабочий процесс с лениво оцененными функциями вокруг обернутого объекта, да?

enter image description here

Хотя построение его из функций работает, я лично был бы склонен построить монаду из какого-то пользовательского типа; кажется слишком легким сопоставлять функции, которые действуют на монадический тип или его «базовый» тип с экземплярами самой монады . Вы в основном строите идентификационную монаду , используя функции; Я был бы более склонен просто создать класс или интерфейс с именем, которое отражает цель, для которой вы помещаете монаду идентификации.

Вы также можете рассмотреть возможность переименования ваших методов. Ваше «To» традиционно называется «Bind», а ваше «ToIdentity» традиционно называется «Unit».

То есть шаблон монады для типа монады M<T> обычно имеет методы:

public static M<V> Bind<U, V>(this M<U> m, Func<U, M<V>> k)

и

public static M<T> Unit<T>(this T value)

Привязка позволяет вам реализовать композицию функций для монад, аналогичную функциям, которые составляются для «базовых» типов монад.

Подробное описание чудес монад в C # см. В моей замечательной статье Уэса Дайера по этому вопросу:

http://blogs.msdn.com/b/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx

Чтобы ответить на ваш актуальный вопрос:

Они уже есть в библиотеке .net?

Эти точные функции не находятся в рамках. Но функции очень похожи на те, которые существуют в рамках. Например, SelectMany на IEnumerable<T> аналогичен вашему To методу; он реализует операцию монадического связывания для последовательностей. new Nullable<int>(123) аналогично вашему методу "ToIdentity"; он реализует монадическую единицу операции для «возможно, монады». И так далее.

Система типов CLR недостаточно богата, чтобы выразить образец монады в целом ; для этого вам нужна система «более высокого» типа, как в Haskell. Вам придется создавать каждую конкретную монаду самостоятельно. Тем не менее, похоже, что вы уже в пути.

Еще несколько мыслей об использовании монад в C # -подобных языках:

Монады в C # - почему реализации Bind требуют, чтобы переданная функция возвращала монаду?

Монада на простом английском? (Для программиста ООП без фона FP)

Почему в предстоящем .NET 4.0

нет ничего похожего на IMonad

Помогите разработчику C # понять: что такое монада?

2 голосов
/ 23 января 2012

Вы можете использовать Ленивый для значений отложенной загрузки.

Lazy<int> lazy = new Lazy<int>(() => delayEvaluatingMe());
int delayed = lazy.Value;
...