在 where 语句中使用声明引用器

如何解决在 where 语句中使用声明引用器

我正在实现一个基于使用标准 haskell 函数/组合器来构建数据库查询的 DSL。从实现 POV 中,我决定在查询中表示变量,如下所示:

newtype Variable = Var { fromVar :: Text }

然而,这迫使用户经常写 Var "something",所以我决定 编写一个自动执行此操作的 quasiquoter。

这是 DSL 的示例:

{-# LANGUAGE OverloadedStrings #-}
maxQuery :: Query MAX
maxQuery = match
         ( sch `isa` "school"
         $ forWhich "ranking" `labelMatches` ran $ε)
         `get` [ran]
         `max` [ran]
    where 
        [sch,ran] = map Var ["sch","ran"] 

我希望它是什么:

maxQuery :: Query MAX
maxQuery = match
         ( sch `isa` "school"
         $ forWhich "ranking" `labelMatches` ran $ε)
         `get` [ran]
         `max` [ran]
    where [defVars| sch ran |] 

或类似的东西。

我写的quasiquoter在这里

{-# LANGUAGE TemplateHaskell #-}
module TypeDBTH where 
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Quote
import Data.List.Split
import Data.Text (pack)

mkVars :: [String] -> Dec
mkVars vars = ValD 
                (ListP (map (VarP . mkName) vars))
                (normalB (ListE (map (\v -> AppE (ConE $ mkName "Var")
                                          $ AppE (VarE $ mkName "pack")
                                                 (LitE $ StringL v))
                                     vars)))
                []

defVars :: QuasiQuoter
defVars = QuasiQuoter { quoteDec = quoteVars }
                 --,quoteExp = expQuoteVars }

quoteVars :: String -> Q [Dec]
quoteVars = return . return . mkVars . filter (/= "") . splitOn " "

expQuoteVars :: String -> Q Exp
expQuoteVars s = return $ LetE [(mkVars . filter (/= "") . splitOn " " $ s)] (LitE $ StringL "x")

本来我只写了quoteVars。为了在 ghci 中进行测试,我添加expQuoteVars。 但是,现在删除一个并尝试编写

...
    where [defVars| sch ran |] 

给我留下两个错误

lib/TypeDBQuery.hs:806:1: error:
    parse error (possibly incorrect indentation or mismatched brackets)

因为 where [quasiquoter] 后面没有任何内容

lib/TypeDBQuery.hs:807:5: error:
    • Exception when trying to run compile-time code:
        lib/TypeDBTH.hs:18:11-46: Missing field in record construction quoteExp

      Code: Language.Haskell.TH.Quote.quoteExp defVars " sch ran "
    • In the quasi-quotation: [defVars| sch ran |]
    |
807 | x = [defVars| sch ran |] 
    |     ^^^^^^^^^^^^^^^^^^^^

我如何将准引用器用于 quoteDec 而不是 quoteExp? 这可能吗?

如果这更容易的话,我也愿意像这样使用它:

maxQuery :: Query MAX
maxQuery = let [defVars | sch ran |] in
                $ match
                ( sch `isa` "school"
                $ forWhich "ranking" `labelMatches` ran $ε)
                `get` [ran]
                `max` [ran]

我查看了 wiki.haskell.org 和 TH 模块的“教程”和信息站点,但不知道如何执行此操作... https://wiki.haskell.org/Template_Haskell#What_to_do_when_you_can.27t_splice_that_there https://wiki.haskell.org/Quasiquotation https://wiki.haskell.org/A_practical_Template_Haskell_Tutorial

解决方法

不幸的是,您只能在顶级声明中使用声明准引号。来自the documentation

准引号可能会代替

  • 表达
  • 一种模式
  • 一种类型
  • 顶级声明

您可以考虑使用 OverloadedStrings 代替 TH:

instance IsString Variable where
  fromString str = Var (pack str)

maxQuery :: Query MAX
maxQuery = match
         ( "sch" `isa` "school"
         $ forWhich "ranking" `labelMatches` "ran" $ε)
         `get` ["ran"]
         `max` ["ran"]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?