模板Haskell中准引号内的类型检查

模板Haskell中准引号内的类型检查,haskell,types,metaprogramming,type-systems,Haskell,Types,Metaprogramming,Type Systems,我正在努力熟悉,让我惊讶的是,下面的代码是在ghc(版本6.10.4)下编译的 main=do 让 y=[|“你好”+1 |] putStr“” 这对我来说意味着在准引号中没有类型检查。这不是我在阅读Haskell模板上的原始内容后所期望的。此外,以下程序不编译 main = do let y = [| "hello" && True |] putStr "" main=do 让 y=[|“你好”&&True] putStr“” 这是怎么回事?模板

我正在努力熟悉,让我惊讶的是,下面的代码是在
ghc
(版本6.10.4)下编译的

main=do 让 y=[|“你好”+1 |] putStr“” 这对我来说意味着在准引号中没有类型检查。这不是我在阅读Haskell模板上的原始内容后所期望的。此外,以下程序不编译

main = do let y = [| "hello" && True |] putStr "" main=do 让 y=[|“你好”&&True] putStr“”
这是怎么回事?

模板Haskell有两个主要操作:

  • 提升:
    [| |]
  • 拼接
    $()
当您将某个内容包装在Oxford括号中时,您会延迟其类型检查(和计算),而是构建一个AST片段,当它重新拼接时,将对其进行类型检查

可以观察到生成的AST:

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
main = print =<< runQ  [| "hello" + 1 |]
{-#语言模板haskell}
导入语言.Haskell.TH
main=print=:t[|“hello”+1 |]
[|“你好”+1 |]::Q Exp
*Main>$([|“hello”+1 |])
:1:4:
没有(Num[Char]的实例)
源于字面上的“1”

正如我们所料。因此,是的,表达式是经过类型检查的,但在后期,当拼接回程序时。

看起来GHC确实对所有引用进行了类型检查,但假设所有生成的实例约束都可以得到满足

在此代码中:

main = do
   let
       y = [| "hello" + 1 |]
   putStr ""
 main = do
   let
      y = [| "hello" && True |]
   putStr ""
在假设有Num字符串实例的情况下,y括号是可键入的。由于GHC不能确定在插入y之前不会引入这样的实例,所以它不会给出类型错误

在此代码中:

main = do
   let
       y = [| "hello" + 1 |]
   putStr ""
 main = do
   let
      y = [| "hello" && True |]
   putStr ""
无论您设置的是什么实例环境,y都无法成功拼接


这只是Template Haskell的类型检查机制过于宽松的一个例子——更多的例子将在Simon PJ的博客文章中讨论,他在文章中建议更改为根本不检查任何引用。

谢谢你,Don。我仍然不明白的是为什么[|“hello”+1 |]类型检查,但[|“hello”&&1 |]不检查(即使没有拼接)。佩顿·琼斯(Peyton Jones)的原稿在第66页上写道:“类型检查术语e立即检测到任何内部类型不一致;例如,[|‘a’+True]将立即被拒绝”。好吧,这就解释了这一点。谢谢你,麦克斯!