Ответ 1
Если вы измените порядок своего кода следующим образом, он будет работать:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data None = None { _f :: Int }
type Simpl = Env
type Env = Int
makeLenses ''None
Когда вы используете сращивания Template Haskell для добавления новых объявлений верхнего уровня в ваш код, как это делает makeLenses
, порядок объявлений в вашем коде имеет значение!
Причина в том, что обычно компиляция программы Haskell предполагает сначала собирать все объявления верхнего уровня и переупорядочивать их внутри, чтобы поместить их в порядок зависимостей, а затем компилировать их один за другим (или группировать по группам для взаимно-рекурсивных объявлений).
С появлением новых деклараций путем запуска произвольного кода, поскольку GHC не знает, какие объявления makeLenses
могут потребоваться для запуска, а также он не знает, какие новые объявления он будет производить. Таким образом, он не может поместить весь файл в порядок зависимостей и просто отказаться от него и ожидает, что пользователь сделает это самостоятельно, по крайней мере, для решения вопроса о том, должны ли объявления проходить до или после сращивания.
Единственная онлайн-ссылка, которую я могу найти, объясняет это в оригинальной бумаге шаблона Haskell, раздел 7.2, где говорится, что алгоритм
- Группируйте объявления следующим образом:
[d1,...,da]
splice ea
[da+2,...,db]
splice eb
...
splice ez
[dz+2,...,dN]
где единственными объявлениями сплайсинга являются те, которые указаны явно, так что каждая группа
[d1,...,da]
и т.д. - все обычные объявления Haskell.
- Выполните обычный анализ зависимостей, а затем проверку типов в первой группе. Все его свободные переменные должны быть в объеме.
Таким образом, проблема заключается в том, что первая группа объявлений перед сращиванием обрабатывается отдельно во вторую группу после сращивания и не может видеть определение Env
.
Мое общее правило заключается в том, чтобы по возможности вставлять такие сращивания в нижнюю часть файла, но я не думаю, что это гарантирует, что это всегда будет работать.