Списковые включения (ZF-выражения) с нулевыми квалификаторами
Списковые включения (или ZF-выражения) включают в себя последовательность квалификаторов , которые могут быть генераторами или булевыми выражениями («выражения фильтра»), действующими как охранники.
Понимание списка без квалификатора — например,[1 | ]
–(видимо) допустимо в Miranda (стр. 130), но недействительно в Haskell , (стр. 42) – я пробовал это вghci
интерпретатор– и (очевидно) недействителен в Clean.
(Конечно, мы могли бы имитировать это, добавивTrue
охрана, например[1 | True]
. Но это более подробно)
Примером использования спискового понимания без определителя в литературе 1 (стр. 134-136) является следующий пример эквационального рассуждения:
[E | ] ++ L = [E] ++ L = (E:[]) ++ L = E:L
Почему разработчики языков программирования Haskell и Clean отказались от спискового понимания без квалификаторов? Есть ли что-то, что может вызвать плохое взаимодействие функций в этих языках, но не в Миранде?
Использованная литература:
Саймон Л. Пейтон Джонс. 1Реализация языков функционального программирования . Прентис Холл. 1987.
Отчет Haskell 98, 2раздел 3.11 «Понимание списков» . 1998.
Питер Вентворт. 3Введение в функциональное программирование с использованием объятий . 2013.
Ринус Пласмейер; Марко ван Экелен; Джон ван Гронинген. 4Отчет о чистом языке, версия 2.2 . 2011.
1 ответ
Я думаю, что очевидный ответ заключается в том, что нет технической причины запрещать включение списков с пустой последовательностью квалификаторов. Требование чисто синтаксическое. Так уж получилось, что в разделе 3.11 исходного отчета Haskell98 указана грамматика, которая требует, чтобы список квалификаторов был непустым, и правила трансляции, превращающие его в выражение ядра, предполагают, что это так. GHC подчиняется этой грамматике, поэтому такое выражение, как[ 10 | ]
отклоняется с ошибкой синтаксического анализа.
С технической точки зрения, простое упрощение грамматики и добавление одного правила перевода:
[ e | ] = [ e | True ]
обратился бы к этому.
Собственно, документация для GHC
MonadComprehensions
расширение фактически обеспечивает перевод для этого случая:
[ e | ] = return e
а остальные правила перевода в основном предполагают, что случаи формы:
[ e | q, Q ]
относятся к частному случаю:
[ e | q ]
сQ
принимается за пустое.
Как только вы пройдете парсер, остальная часть GHC отлично справится с этим особым случаем. В частности, если вы используете Template Haskell, чтобы обойти синтаксический анализатор и создать включение без квалификаторов, вы увидите, что оно оценивается так, как ожидалось. (Отдельные модули здесь необходимы из-за ограничения фазы TH.)
--
-- EmptyComprehension.hs
--
module EmptyComprehension where
import Language.Haskell.TH
-- equivalent to "[ 10 | ]"
x :: ExpQ
x = compE [noBindS (litE (integerL 10))]
--
-- Test.hs
--
{-# LANGUAGE TemplateHaskell #-}
import EmptyComprehension
main = print $(x) -- will print `[10]`
Что касается того, почему язык был разработан таким образом, я думаю, что это было либо недосмотром, либо, возможно, это было рассмотрено в какой-то момент, но синтаксис[10 | ]
считалось слишком странным, чтобы допустить его.
В соответствующей заметке, пустоcase
также были запрещены исходным отчетом Haskell98, но затем разрешены черезEmptyCase
расширение, когда было обнаружено, что они действительно могут быть полезны.
Я думаю, у вас могут возникнуть проблемы с убеждением кого-либо в том, что подобное расширение для понимания имеет смысл. В комментариях вы упоминаете автоматическую генерацию исходников, но этот случай легко обработать специально или добавить доп.True
квалификатор для каждого всеобъемлющего (или, если вы создаете исходный код с помощью TemplateHaskell, просто обойдите ограничение напрямую).