Spec-Zone.ru › Haskell 9

6.2.17. Более либеральный синтаксис для аргументов функций

BlockArguments
Since:

8.6.1

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

В Haskell 2010 определённые виды выражений могут использоваться без скобок в качестве аргумента оператора, но не в качестве аргумента функции. К ним относятся do, лямбда-, if, case, и let выражения. Некоторые расширения GHC также определяют конструкции языка такого типа: mdo (Рекурсивный do-notation), \case (Лямбда-case) и proc (Стрелочная нотация).

Расширение BlockArguments позволяет использовать эти конструкции непосредственно в качестве аргумента функции. Например:

when (x > 0) do
  print x
  exitFailure

будет разбор как:

when (x > 0) (do
  print x
  exitFailure)

и

withForeignPtr fptr \ptr -> c_memcpy buf ptr size

будет разбор как:

withForeignPtr fptr (\ptr -> c_memcpy buf ptr size)

6.2.17.1. Изменения в грамматике

Отчёт Haskell определяет lexp нетерминал следующим образом (* указывает правило, которое нас интересует):

lexp  →  \ apat1 … apatn -> exp            (lambda abstraction, n ≥ 1)  *
      |  let decls in exp                  (let expression)             *
      |  if exp [;] then exp [;] else exp  (conditional)                *
      |  case exp of { alts }              (case expression)            *
      |  do { stmts }                      (do expression)              *
      |  fexp

fexp  →  [fexp] aexp                       (function application)

aexp  →  qvar                              (variable)
      |  gcon                              (general constructor)
      |  literal
      |  ( exp )                           (parenthesized expression)
      |  qcon { fbind1 … fbindn }          (labeled construction)
      |  aexp { fbind1 … fbindn }          (labelled update)
      |  …

Расширение BlockArguments перемещает эти правила вывода под aexp

lexp  →  fexp

fexp  →  [fexp] aexp                       (function application)

aexp  →  qvar                              (variable)
      |  gcon                              (general constructor)
      |  literal
      |  ( exp )                           (parenthesized expression)
      |  qcon { fbind1 … fbindn }          (labeled construction)
      |  aexp { fbind1 … fbindn }          (labelled update)
      |  \ apat1 … apatn -> exp            (lambda abstraction, n ≥ 1)  *
      |  let decls in exp                  (let expression)             *
      |  if exp [;] then exp [;] else exp  (conditional)                *
      |  case exp of { alts }              (case expression)            *
      |  do { stmts }                      (do expression)              *
      |  …

Теперь lexp нетерминал избыточен и может быть удалён из грамматики.

Обратите внимание, что это изменение опирается на существующее метаправило для разрешения неоднозначностей:

Грамматика неоднозначна в отношении объёма лямбда-абстракций, выражений let и условных выражений. Неоднозначность разрешается метаправилом, которое предполагает, что каждая из этих конструкций распространяется как можно дальше вправо.

Например, f \a -> a b будет разбор как f (\a -> a b), а не как f (\a -> a) b.

© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/9.12.1/docs/users_guide/exts/block_arguments.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API