Как повторить поведение 'name в соединении TH - PullRequest
0 голосов
/ 08 мая 2018

Рассмотрим этот файл на Haskell:

{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
module Text (main) where

import Test.Inspection

import Data.Text as T
import Data.Text.Encoding as E
import Data.ByteString (ByteString)

import Language.Haskell.TH

toUpperString :: String -> String
toUpperString = T.unpack . T.toUpper . T.pack

toUpperBytestring :: ByteString -> String
toUpperBytestring = T.unpack . T.toUpper . E.decodeUtf8

do Just n <- lookupValueName "toUpperString"
   inspect $ n `hasNoType` ''T.Text
inspect $ 'toUpperBytestring `hasNoType` ''T.Text

main :: IO ()
main = return ()

Он использует Template Haskell для определения обязательств по тестированию, которые тестируются плагином GHC при инспекционном тестировании.

Под капотом инспекционное тестирование передает имя Template Haskell в аннотации и преобразует его в имя Core, используя thNameToGhcName, а затем пытается найти это имя в текущем модуле.

Это прекрасно работает, если я создаю шаблон имени Хаскелла, используя 'foo, но не работает, если я использую lookupValueName.

  • Почему они разные?
  • Как я могу воссоздать поведение 'foo, когда у меня есть строка?

(Почему я не просто использую 'foo? Потому что я хочу динамически создавать обязательства, поэтому у меня есть код Template Haskell, который определяет множество таких функций и обязательств.)

1 Ответ

0 голосов
/ 08 мая 2018

Проблема в этом случае не столько в том, что Name, возвращаемый 'foo против lookupValueName, отличается, но в том, что использование 'foo поддерживает foo в течение всей компиляции модуля, тогда как lookupValueName "foo" нет. Затем GHC удаляет привязку "foo" и проверочные проверки отключает ее.

И действительно, удаление списка экспорта из модуля, который хранит все привязки верхнего уровня, устраняет проблему.

...