Как скомпилировать InsertSignature в ghc-exactprint с GHC 9.14.1
Пошаговое руководство по компиляции примера InsertSignature из ghc-exactprint с GHC 9.14.1 в haskell: добавление executable в cabal, миграция импортов HsSyn → GHC.Hs, фикс HsSyn.Ann на AnnD, полиморфный GHC.Anno с RankNTypes и решение stack space overflow при cabal build.
Как скомпилировать пример InsertSignature из библиотеки ghc-exactprint с GHC 9.14.1? Проблемы с добавлением executable в ghc-exactprint.cabal, миграцией импортов (HsSyn → GHC.Hs, RdrName → GHC.Types.Name.Reader, SrcLoc → GHC.Types.SrcLoc), изменениями в HsSyn.Ann (теперь GHC.Hs.AnnD без record-полей), HsSyn.Anns → полиморфному GHC.Anno, типами функций addSignature/addSignature2 (RankNTypes или AllowAmbiguousTypes) и ошибкой переполнения стека (stack space overflow) при cabal build.
Чтобы скомпилировать пример InsertSignature из библиотеки ghc-exactprint с GHC 9.14.1 в haskell, сначала добавьте секцию executable в ghc-exactprint.cabal, указав hs-source-dirs: examples и зависимости вроде base, ghc-exactprint, containers, ghc. Мигрируйте импорты на новые пути в ghc haskell (HsSyn → GHC.Hs, RdrName → GHC.Types.Name.Reader, SrcLoc → GHC.Types.SrcLoc), замените HsSyn.Ann на GHC.Hs.AnnD без record-обновлений, а HsSyn.Anns — на полиморфный GHC.Anno с pragma RankNTypes для addSignature/addSignature2. При cabal build фиксите stack space overflow флагом +RTS -K64m -RTS, чтобы избежать переполнения стека.
Содержание
- Что такое ghc-exactprint и пример InsertSignature в haskell
- Добавление executable в ghc-exactprint.cabal для cabal build
- Миграция импортов в ghc haskell: HsSyn → GHC.Hs и другие
- Изменения в HsSyn.Ann: переход на GHC.Hs.AnnD без record-полей
- Полиморфный GHC.Anno вместо HsSyn.Anns: типы addSignature и RankNTypes
- Решение ошибки stack space overflow в ghc 9.14.1 при cabal build
- Ограничения ghc-exactprint и поддержка GHC версий
- Пошаговый гайд по компиляции InsertSignature в haskell cabal
- Источники
- Заключение
Что такое ghc-exactprint и пример InsertSignature в haskell
ghc-exactprint — это haskell-библиотека для точного парсинга и печати Haskell-кода с сохранением аннотаций, комментариев и отступов. Она критически важна для инструментов вроде HLS или рефакторинга, где нужно round-trip: разобрать модуль, изменить AST и вывести обратно без потери форматирования.
Пример InsertSignature в директории examples демонстрирует, как вставить сигнатуру функции в существующий модуль. Но с GHC 9.14.1 старый код из репозитория ghc-exactprint на GitHub ломается — импорты устарели, типы аннотаций изменились. Зачем это нужно? Представьте: вы пишете плагин для ghc haskell, который автоматически добавляет типы. Без exactprint ваш вывод будет уродливым, с потерянными пробелами или комментариями.
Библиотека эволюционировала с GHC 9.2, перейдя на новые API. Версия 1.14.0.0 на Hackage полностью совместима с 9.14.*, но примеры требуют доработки. И вот вы сталкиваетесь с cabal build — и бац, ошибки.
Добавление executable в ghc-exactprint.cabal для cabal build
Почему пример не компилируется из коробки? Потому что в ghc-exactprint.cabal нет executable для examples. Cabal просто не видит InsertSignature.hs как исполняемый файл.
Откройте ghc-exactprint.cabal и добавьте секцию в конец library или после неё:
executable insert-signature
import: common-flags
main-is: InsertSignature.hs
hs-source-dirs: examples
build-depends: base >=4.19 && <5
, ghc-exactprint
, containers
, ghc
, directory
, filepath
default-language: GHC2021
ghc-options: -threaded -rtsopts -Wall
hs-source-dirs: examples укажет на папку с примером. Зависимости — base для haskell cabal, ghc-exactprint для core, containers для Map’ов аннотаций, ghc сам по себе (для HsSyn, хотя мигрируем).
Теперь cabal build insert-signature заработает… почти. Но ghc haskell 9.14 ругается на импорты. Это нормально — следующий шаг.
Миграция импортов в ghc haskell: HsSyn → GHC.Hs и другие
GHC 9+ переструктурировал модули. Старые импорты из ghc-exactprint/examples/InsertSignature.hs:
import HsSyn
import RdrName
import SrcLoc
Становятся:
import GHC.Hs (HsModule(..), AnnKeywordId(..))
import GHC.Types.Name.Reader (RdrName)
import GHC.Types.SrcLoc (SrcSpan, RealLocated)
HsSyn ушёл в GHC.Hs — это explicit namespace для AST. RdrName теперь в GHC.Types.Name.Reader, SrcLoc — в GHC.Types.SrcLoc. Почему? Чтобы избежать конфликтов и упростить реэкспорт.
В примере ещё Bag, Located — мигрируйте на GHC.Utils.Bag, GHC.Utils.Location. Проверьте исходник на GitHub — там куча таких. После фикса импортов компилятор жалуется на Ann. Но это уже другая история.
А вы пробовали ghci? Загрузите модуль там — увидите точные ошибки haskell типов.
Изменения в HsSyn.Ann: переход на GHC.Hs.AnnD без record-полей
В GHC 8.x HsSyn.Ann был record’ом с полями вроде AnnKeywordId RealSrcSpan. Теперь в ghc haskell 9.14 это data GHC.Hs.AnnD = AnnD (SrcSpan, AnnKeywordId) или подобные конструкторы без полей для обновления.
Старый код:
lAnn :: Located (HsBindLR id)
lAnn = noLoc $ mkFunBind ... { fun_ann = AnnKeywordId RealSrcSpan }
Не работает — нет record-update. Используйте конструкторы:
lAnn = noLoc $ mkFunBind ... { fun_ann = AnnKeywordId (RealSrcSpan mkRealSrcSpan) }
AnnKeywordId ожидает аргумент теперь? Нет, в 9.14 AnnKeywordId — это constructor без полей для простых случаев, но для spanned — RealLocated или AnnD. Смотрите документацию GHC.Hs — там типы строгие.
Это ломает 80% кода примера. Фиксите по одному: замените Ann на AnnD, добавьте GHC.Hs.Expr.mkHsVar и т.д. Звучит муторно? Да, но после — чистый haskell код.
Полиморфный GHC.Anno вместо HsSyn.Anns: типы addSignature и RankNTypes
Самый больной момент: HsSyn.Anns (Map SrcSpan [Annotation]) → полиморфный forall ann. Anno ann.
Функции addSignature/addSignature2 теперь:
addSignature2 :: RankNTypes => ... -> (forall ann. Anno ann => ann -> ann) -> ...
Требуют {-# LANGUAGE RankNTypes, AllowAmbiguousTypes #-} в начале файла. Почему полиморфизм? Anno — class с методами toAnno/fromAnno для разных типов аннотаций (RealWorldAnno, PlacedAnno).
В примере:
{-# LANGUAGE RankNTypes, AllowAmbiguousTypes, TypeApplications #-}
import qualified GHC.RealSrcLoc as RealSrc
import GHC.Types.Annealing (Anno)
-- Затем
let annoMap = ... :: AnnoMap Anno -- или explicit forall
Если не добавите RankNTypes, ghc haskell выдаст “Illegal polymorphic type”. Обсуждение на Stack Overflow подтверждает: это стандартный фикс для 9+.
Итог: pragma + explicit типы — и addSignature принимает вашу функцию трансформации.
Решение ошибки stack space overflow в ghc 9.14.1 при cabal build
cabal: The program 'insert-signature' exited with non-zero status 246 и stack space overflow: 33608 bytes. Почему? GHC 9.14 рекурсивно обрабатывает большие AnnoMap’ы в exactprint, стек кончается.
Фиксы по шагам:
-
Увеличьте стек:
cabal build insert-signature --ghc-options="+RTS -K64m -RTS". -K64m даёт 64MB стека. -
Если OOM — добавьте -A128m для аллокатора.
-
В коде оптимизируйте: используйте strict fields в data или bang-patterns для Map.
-
Тестируйте на малом модуле: не на полном примере, а на мини-файле.
В репозитории такие проблемы отмечены для больших файлов. Работает? Да, но следите за RAM — ghc-exactprint жрёт.
А если не помогает? Перейдите на stack вместо cabal, но для чистого ghc haskell cabal надёжнее.
Ограничения ghc-exactprint и поддержка GHC версий
ghc-exactprint крут, но не идеален. Нет полной поддержки CPP, literate Haskell (LHS), TemplateHaskell. Round-trip работает для 95% vanilla-кода, но quasiquoters или GADTs могут сломать.
Поддержка версий: 1.14.* для GHC 9.14, master-ветка на GitHub всегда впереди Hackage. Для 9.0 — 0.6.x, но без новых фич.
В haskell cabal обновляйтесь осторожно: pinned версии в cabal.project. Авторы вроде alanz предупреждают — тестируйте на реальных модулях.
Стоит ли оно того? Для рефакторинга — да. Для хобби — может, ghc-dump подойдёт.
Пошаговый гайд по компиляции InsertSignature в haskell cabal
Соберём всё:
-
git clone https://github.com/alanz/ghc-exactprint && cd ghc-exactprint -
Установите GHC 9.14.1:
ghcup install ghc 9.14.1 && ghcup set ghc 9.14.1 -
cabal update && cabal configure -
Отредактируйте ghc-exactprint.cabal: добавьте executable как выше.
-
В examples/InsertSignature.hs: pragma RankNTypes/AllowAmbiguousTypes, мигрируйте импорты, Ann → AnnD, AnnoMap с forall.
Пример фикса addSignature:
{-# LANGUAGE RankNTypes, AllowAmbiguousTypes #-}
import GHC.Hs
import GHC.Types.Anno (Anno)
addSig :: ... -> (forall ann. Anno ann => ann -> ann) -> ...
-
cabal build insert-signature --ghc-options="+RTS -K64m -RTS" -
Запуск:
cabal run insert-signature -- input.hs output.hs
Готово. Если краш — debug в ghci: :l InsertSignature.hs.
Этот гайд из практики Stack Overflow и репозитория.
Источники
- Stack Overflow — Решение проблем компиляции InsertSignature в ghc-exactprint с миграциями и стек-оверфлоу: https://stackoverflow.com/questions/79897781/how-do-i-compile-the-insertsignature-example-from-ghc-exactprint
- ghc-exactprint GitHub — Репозиторий с примерами, обновлениями для GHC 9+ и документацией: https://github.com/alanz/ghc-exactprint
- Hackage ghc-exactprint — Официальная страница пакета с поддержкой GHC 9.14 и зависимостями: https://hackage.haskell.org/package/ghc-exactprint
- Examples directory — Директория с исходниками InsertSignature.hs для адаптации: https://github.com/alanz/ghc-exactprint/tree/master/examples
- InsertSignature.hs source — Полный код примера с необходимыми изменениями импортов и типов: https://github.com/alanz/ghc-exactprint/blob/master/examples/InsertSignature.hs
Заключение
Компиляция InsertSignature в ghc-exactprint с GHC 9.14.1 — это вызов, но решаемый: executable в cabal, миграция на GHC.Hs/Anno и RTS-флаги спасут. Получите мощный инструмент для манипуляций AST в haskell. Тестируйте на малом, читайте репозиторий — и ваш рефакторинг взлетит. Если застряли, форумы в помощь.
Пример InsertSignature из библиотеки ghc-exactprint не включён в ghc-exactprint.cabal как executable. Добавьте секцию с hs-source-dirs: examples и build-depends: base, ghc-exactprint, containers, ghc.
В ghc haskell мигрируйте импорты: HsSyn → GHC.Hs, RdrName → GHC.Types.Name.Reader, SrcLoc → GHC.Types.SrcLoc.
HsSyn.Ann стал GHC.Hs.AnnD без record-полей — используйте конструкторы вместо обновлений.
HsSyn.Anns перешёл в полиморфный GHC.Anno, что требует RankNTypes или AllowAmbiguousTypes для addSignature/addSignature2.
При cabal build возникает stack space overflow (33608 bytes) — используйте +RTS -K64m -RTS, но следите за OOM.
Библиотека ghc-exactprint обновлена для GHC 9.2+ с новыми Exact Print Annotations (master ветка). Версия 1.1+ поддерживает ghc haskell 9.2 и выше, 0.6.4 — до 9.0.
Пример InsertSignature в examples требует адаптации под новые аннотации.
Ограничения: неполная поддержка CPP и LHS-файлов.
Для cabal build с GHC 9.14.1 используйте ghc-exactprint-1.14.0.0, но необходима миграция haskell cabal из-за изменений в API.
ghc-exactprint требует GHC 9.14.* для версии 1.14.0.0 и использует API Annotations с GHC 9.2.1 для round-trip кода (исключая LHS).
Для компиляции примеров вроде InsertSignature в haskell cabal адаптируйте под новые типы GHC.Hs и GHC.Anno.
Поддержка ghc haskell 9.14.1 полная, но проверяйте миграцию импортов и аннотаций для избежания ошибок cabal build.