Подтвердить что ты не робот

Выделение внутри квазицикла в шаблоне Haskell

Я пытаюсь ознакомиться с Template Haskell, и, к моему удивлению, код ниже компилируется под ghc (версия 6.10.4).

    main = do
       let
           y = [| "hello" + 1 |]
       putStr ""

Это говорит мне о том, что в квазициклах нет никакой проверки. Это не то, что я ожидал после прочтения оригинального paper в Template Haskell. Кроме того, следующая программа не компилируется.

    main = do
       let
          y = [| "hello" && True |]
       putStr ""

Что здесь происходит?

4b9b3361

Ответ 1

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

В этом коде:

main = do
   let
       y = [| "hello" + 1 |]
   putStr ""

Кран y подлежит типу в предположении, что мы имеем экземпляр Num String. Поскольку GHC не может точно сказать, что вы не представите такой экземпляр до того, как будет сражаться, тогда он не даст ошибку типа.

В этом коде:

 main = do
   let
      y = [| "hello" && True |]
   putStr ""

Нет никакого способа, чтобы y можно было успешно спланировать успешно, независимо от того, какую среду среды вы настроили.

Это всего лишь один пример того, как механизм проверки шаблонов Template Haskell слишком мягкий. Дальнейшие примеры обсуждаются в блоге Саймона PJ в http://hackage.haskell.org/trac/ghc/blog/Template%20Haskell%20Proposal, где он предлагает изменение типа не проверяет любые цитаты вообще.

Ответ 2

Шаблон Haskell имеет две основные операции:

  • Подъем: [| |]
  • сращивание $( )

Когда вы обертываете что-то в скобках в Оксфорде, вы задерживаете его проверку типа (и оценку) и вместо этого создаете фрагмент AST, который будет проверяться по типу, когда он снова сращивается.

АСТ, который построен, можно наблюдать:

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
main = print =<< runQ  [| "hello" + 1 |]

Запуск этой программы (или ввод выражения скобки в GHCi), и мы получим хорошо сформированный АСТ, но тот, который не является корректным, если рассматривать его как фрагмент Haskell:

InfixE (Just (LitE (StringL "hello" ))) (VarE GHC.Num. +) (Just (LitE (IntegerL 1)))

Теперь, когда мы пытаемся связать его, введите проверку:

*Main> :t [| "hello" + 1 |]
[| "hello" + 1 |] :: Q Exp

*Main> $( [| "hello" + 1 |] )
<interactive>:1:4:
  No instance for (Num [Char])
    arising from the literal `1'

Как и ожидалось. Итак, да, выражения TH проверяются по типу, но в конце концов, когда они снова подключены к программе.