LINQ запрашивают выражения, которые воздействуют на типы (монады?) кроме IEnumerable <T> — Возможные применения?

Я читаю книгу Реальное функциональное программирование Tomas Petricek и Jon Skeet, и мне нелегко переваривать раздел по вычислению expressions1) (иначе монады).

Через эту книгу я узнал, что — вопреки моему предыдущему опыту — выражения запроса LINQ не ограничиваются IEnumerable, но может работать над другими пользовательскими типами также. Это кажется очень интересным мне, и я задаюсь вопросом, существуют ли сценарии где синтаксис выражения запроса (from x in ... select ...) было бы хорошее соответствие.


Некоторая вводная информация:

По-видимому, такие пользовательские типы называют типами вычисления, которые изображаются как являющийся по существу тем же самым как монады в Haskell. Я никогда не мог схватить, каковы точно монады, но согласно книге, они определяются посредством двух названных операций, связывают и возвращаются.

В функциональном программировании подписи типа этих двух операций были бы (я думаю):

//    Bind      :    M -> (A' -> B') -> M
//
//    Return    :    A' -> M

где M имя одноместного типа.

В C# это соответствует:

Func< M, Func, M >   Bind;

Func< A, M >                 Return;

Оказывается что LINQ's Enumerable.Select (оператор проекции), имеет точно ту же подпись как связывать операция с M := IEnumerable.

Мой пользовательский тип вычисления LINQ:

Используя это знание, я могу теперь записать пользовательский тип вычисления, который не является IEnumerable:

// my custom computation type:
class Wrapped
{
    // this corresponds to the Return operation:
    public Wrapped(A value)
    {
        this.Value = value;
    }

    public readonly A Value;
}

static class Wrapped
{
    // this corresponds to the Bind operation:
    public static Wrapped Select(this Wrapped x, Func selector)
    {
        return new Wrapped(selector(x.Value));
    }
}

И теперь я могу использовать Wrapped в LINQ запрашивают выражения, например:

Wrapped wrapped = new Wrapped(41);

Wrapped answer  = from x in wrapped   // works on int values instead 
                       select x + 1;       // of Wrapped values!

Конечно, этот пример не очень полезен, но он демонстрирует, как выражения запроса могут быть сделаны сделать что-то еще, чем работа с наборами, например, обертывание и разворачивание значений с некоторым типом.


Вопрос:

Вышеупомянутый тип вычисления не кажется очень полезным. Поэтому интересно, чем могло там быть другое разумное использование (помимо обработки наборов), это использует выражения запроса LINQ?


1) Раздел 12.4: "Представляя альтернативные рабочие процессы", начиная на странице 334.

13
задан stakx supports GoFundMonica 4 June 2010 в 10:54
поделиться

3 ответа

Хотя мне не нравится это делать (потому что это немного похоже на жульничество), я думаю, что на этот раз мне придется ответить на свой вопрос.

Я подумал еще об этом. Мой вопрос был несколько наивным. Все сводится к тому, что выражения запроса LINQ (например, из в , где select …), а также ] foreach - это синтаксический сахар поверх другого, более простого синтаксиса.

  • foreach работает со всем, что реализует метод IEnumerator GetEnumerator () . IEnumerable просто выполняет это условие.

  • Точно так же выражения запросов LINQ транслируются в соответствии с некоторыми четко определенными правилами, например из x в xs, где x> 0 select -x становится xs.Where (x => x> 0) .Select (x => -x) . Пока какой-либо тип реализует некоторые или все методы оператора запроса, этот тип можно использовать с LINQ практически для любых целей.

От меня остается вопрос: для чего на самом деле можно использовать LINQ, помимо обработки коллекций; и я думаю, что ответ будет «для очень небольшого другого», потому что структура выражений запросов LINQ довольно жесткая . Вам всегда понадобится из в часть. Кажется, что select … ​​тоже нужен всегда. Если «язык» результирующих выражений не соответствует конкретному потенциальному сценарию, любое из других ключевых слов ( let , orderby , groupby и т. Д. ) не улучшит ситуацию.LINQ был совершенно четко разработан с одной целью - это запрос данных, и полученная грамматика фактически ограничивает LINQ больше, чем это, вероятно, необходимо.

Я сравнил возможности LINQ для целей, отличных от запроса данных, с возможностями вычислительных выражений F #, и они кажутся более гибкими, поскольку требуемых ключевых слов не так много. Что делает их подходящими для большего количества сценариев.

4
ответ дан 2 December 2019 в 01:09
поделиться

LinqToTwitter использует LINQ необычным образом. Вещи в предложении 'from' не являются, по логике, перечислимыми типами. Взгляните на источник :)

3
ответ дан 2 December 2019 в 01:09
поделиться

Мысли:

  • PushLINQ (я и Джон) - меняет LINQ на модель push (а не на модель IEnumerable pull)
  • Reactive Framework / Reactive Extensions - еще одна совершенно другая модель событий, включающая синтаксис LINQ
  • . Я написал API-интерфейс потоковой передачи (ab), используя синтаксис запросов LINQ; Меня это не убедило на 100%, поэтому я отказался от этого, но это было интересно; использовал из ( SelectMany ) и т. д., чтобы выбрать точки ветвления / слияния полностью , не связанные с перечислениями
3
ответ дан 2 December 2019 в 01:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: