Haskell: сделал бы нотацию быть полезным для контекстов кроме монад?

Все мы любим do, и мне было любопытно, если, возможно, этот вид альтернативного синтаксиса теоретически будет полезен за пределами мира монады. Если так, что другие виды вычислений это упростило бы? Имело бы смысл иметь что-то эквивалентное для Применимого, например?

10
задан J Cooper 26 July 2010 в 15:17
поделиться

8 ответов

В отношении самой нотации do может быть полезно подумать, для чего она на самом деле хороша. Как указывает Трэвис Браун, я ранее выступал за использование стиля «функционального приложения» с Monad s и родственными типами, но у этого есть и обратная сторона: Некоторые выражения просто могут Не должно быть написано чисто в стиле приложения прямых функций . Например, следующее может быстро сделать аппликативный стиль неуклюжим:

  • Промежуточные результаты, используемые в нескольких подвыражениях, на разной глубине вложенности
  • Аргументы самой внешней функции, используемые глубоко вложенными в подвыражения
  • Неуклюжий или непоследовательный порядок аргументов, то есть необходимость частично применить функцию к чему-то другому, кроме ее первого аргумента
  • Глубоко встроенное управление потоком на основе промежуточных результатов с общими подвыражениями между ветвями
  • Сопоставление с образцом для промежуточных результатов, особенно в случае извлечения части результата , используя это для дальнейших вычислений, а затем воссоздавая модифицированную версию в качестве следующего результата

Написание такой функции как одного выражения обычно требует либо нескольких вложенных лямбда-выражений, либо абсурдной запутанной ерунды, которая придает бесточечному стилю плохую репутацию .С другой стороны, блок do предоставляет синтаксический сахар для легкого вложенного определения промежуточных результатов со встроенным потоком управления.

Обычно вы, вероятно, извлекаете такие подвыражения и помещаете их в предложение where или что-то в этом роде, но поскольку обычные значения образуют монаду с приложением функции как (>> =) - - а именно монада Identity - вы могли бы вместо этого написать такую ​​функцию в блоке do , хотя люди могут на вас посмеяться.


Помимо области видимости / связывания, блок do делает за вас еще одну вещь - это исключение оператора, связывающего подвыражения вместе. Нетрудно представить себе другие случаи, когда было бы неплохо иметь обозначение для «объединить эти выражения, используя эту функцию в этом блоке», а затем позволить компилятору заполнить пробелы.

В простом случае, когда все выражения имеют один и тот же тип, размещение их в списке с последующим сворачиванием работает хорошо - построение строк таким образом с использованием неслов и несогласованных строк ], например. Преимущество do состоит в том, что он объединяет выражения с общей структурой и совместимыми, но не идентичными типами.

Фактически, тот же самый общий принцип верен для обозначения «скобок идиомы» из статьи Applicative : там, где блоки do используют символы новой строки для исключения монадической конструкции, скобки идиомы используют сопоставление чтобы исключить отмененное приложение функции.Нотация proc для Arrow также аналогична, и другие концепции также могут быть четко выражены таким образом, например:

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

Хотя это не слишком сложно превратить многие из них в один тип или полный экземпляр Monad , было бы неплохо иметь унифицированный, расширяемый бит синтаксического сахара для общей концепции. Конечно, есть общая нить, связывающая все это и многое другое, но это гораздо более обширная тема, на самом деле не имеющая отношения к синтаксису ...

9
ответ дан 3 December 2019 в 13:36
поделиться

Мне кажется, что многие программисты Haskell вообще не любят do , и это один из распространенных аргументов в пользу использования Applicative ], когда вам не нужна вся мощь Монады , так это то, что комбинаторы <$> , <*> и т. д. позволяют очень ясно и кратко стиль кодирования.

Даже для монадического кода многие люди предпочитают явно использовать = << вместо нотации do . Ответ camccann на ваш предыдущий вопрос о <*> дает фантастический аргумент в пользу этого предпочтения.

Я обычно пишу свои первые черновики, используя do , а затем заменяю их комбинаторами по мере исправления. Это всего лишь вопрос моего (не) опыта и вкуса: часто мне легче всего набрасывать вещи в более императивном стиле (что удобнее с do ), но я думаю, что не код обычно красивее.

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

14
ответ дан 3 December 2019 в 13:36
поделиться

Скобки идиомы - хороший способ думать о Applicatives, но они не единственное возможное такое расширение синтаксиса.

Филиппа Каудерой недавно отправила в haskell-cafe предложение о «Аппликативном do» нотации, отметив, что любая функция, которая выглядит примерно так:

foo = do
    x <- bar
    y <- baz
    quux y 1234 x

где переменные связаны <- встречается только в последней строке, может быть реализовано с Applicative - я фактически реализовал макрос на основе синтаксических правил для этого в схеме, которую я назвал 'ado'.

Это полезно в тех случаях, когда порядок аппликативных эффектов отличается от «естественного порядка» и предположение о существовании 'ado' в Haskell просто десахарирует:

foo = (\x y -> quux y 1234 x) <*> bar <*> baz

Однако правила лексической области видимости немного сбивают с толку .

5
ответ дан 3 December 2019 в 13:36
поделиться

В GHC есть препроцессор, который делает это для Arrows: http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/arrow-notation.html

1
ответ дан 3 December 2019 в 13:36
поделиться

Нотация do - это, по сути, способ сказать "преобразовать в лямбды по мере необходимости и распределять >>= между строками".

Когда очевидно, какой оператор используется для сворачивания всего, приятно опустить и использовать оператор "новой строки".

Программируемая новая строка была бы хорошим подходом к созданию списков, аппликативных цепочек и т.д. Для создания списков вам также понадобится "программируемый отступ". На самом деле, можно просто взять три значимых бита и сделать их все перегружаемыми:

  • Begin of do.
  • Между dos.
  • Конец do.

Тогда, наверное, не стоит больше называть это do. Возможно, это должна быть просто скобка.

7
ответ дан 3 December 2019 в 13:36
поделиться

Applicative имеет (гораздо более ограниченные и более компактные) скобки-идиомы, смотрите Прикладное программирование с эффектами, страница 4. В среде Хаскеля Strathclyde Haskell Environment Конора МакБрайда, как мне кажется, реализованы такие скобки.

Я не вижу, как обобщить эти виды специальных синтаксисов, но, возможно, я недостаточно об этом задумывался.

3
ответ дан 3 December 2019 в 13:36
поделиться

BlazeHtml использует нотацию do , хотя на самом деле это просто ] Моноид (хотя и завернут в Монаду , чтобы можно было использовать do ).

Таким образом, подобная запись для Monoid s была бы здесь полезна.

Если вы посмотрите на код моей игры "Defend The King" , то я также много использую mconcat ing, и, как и BlazeHtml, мне бы пригодился хороший поиск синтаксиса для этого.

3
ответ дан 3 December 2019 в 13:36
поделиться

Есть обобщение монад, которое подходит к do нотации - параметризованные монады. Смотрите Beyond Monads от sigfpe. Пример использования:

test1' = do put 1
            x <- get
            put (show x)
            y <- get
            return (x,y)

Это "монада состояний", которая хранит сначала число, а затем строку.

2
ответ дан 3 December 2019 в 13:36
поделиться
Другие вопросы по тегам:

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