gpt4 book ai didi

Haskell:模板 Haskell 和作用域

转载 作者:行者123 更新时间:2023-12-03 21:42:43 26 4
gpt4 key购买 nike

这段代码编译得很好:

data None = None { _f :: Int }
type Simpl = Env

type Env = Int

但是,此代码出现错误:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data None = None { _f :: Int }

type Simpl = Env

makeLenses ''None

type Env = Int

错误:
Not in scope: type constructor or class `Env'

我刚刚添加了一行 makeLenses ''None类型声明之间。
这是否意味着 TemplateHaskell 代码可以改变类型构造函数的范围?

有谁知道有关此问题的详细信息(或如何避免此问题)?

最佳答案

如果您按如下方式重新排序代码,它将起作用:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data None = None { _f :: Int }

type Simpl = Env

type Env = Int

makeLenses ''None

当您使用模板 Haskell 拼接向您的代码添加新的顶级声明时,如 makeLenses确实,代码中的声明顺序突然变得很重要!

原因是,通常编译 Haskell 程序涉及首先收集所有顶级声明并在内部重新排序以将它们按依赖顺序排列,然后逐个编译它们(或逐组进行相互递归声明)。

通过运行任意代码引入新声明,因为 GHC 不知道哪些声明 makeLenses可能需要运行,而且它也不知道它将产生哪些新声明。所以它不能把整个文件放在依赖顺序中,只是放弃并期望用户自己做,至少决定声明应该在拼接之前还是之后。

我能找到的唯一可以解释这一点的在线引用资料在 original Template Haskell paper 中。 ,第 7.2 节,其中说算法是:

  • Group the declarations as follows:

[d1,...,da]
splice ea
[da+2,...,db]
splice eb
...
splice ez
[dz+2,...,dN]

where the only splice declarations are the ones indicated explicitly, so that each group [d1,...,da], etc, are all ordinary Haskell declarations.

  • Perform conventional dependency analysis, followed by type checking, on the first group. All its free variables should be in scope.


所以这里的问题是拼接前的第一组声明被单独处理到拼接后的第二组,看不到 Env的定义.

我的一般经验法则是尽可能将这样的拼接放在文件的底部,但我认为不能保证这将始终有效。

关于Haskell:模板 Haskell 和作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20876147/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com