Программирование

Как скомпилировать 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.

6 ответов 1 просмотр

Как скомпилировать пример 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

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:

haskell
import HsSyn
import RdrName
import SrcLoc

Становятся:

haskell
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) или подобные конструкторы без полей для обновления.

Старый код:

haskell
lAnn :: Located (HsBindLR id)
lAnn = noLoc $ mkFunBind ... { fun_ann = AnnKeywordId RealSrcSpan }

Не работает — нет record-update. Используйте конструкторы:

haskell
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 теперь:

haskell
addSignature2 :: RankNTypes => ... -> (forall ann. Anno ann => ann -> ann) -> ...

Требуют {-# LANGUAGE RankNTypes, AllowAmbiguousTypes #-} в начале файла. Почему полиморфизм? Anno — class с методами toAnno/fromAnno для разных типов аннотаций (RealWorldAnno, PlacedAnno).

В примере:

haskell
{-# 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, стек кончается.

Фиксы по шагам:

  1. Увеличьте стек: cabal build insert-signature --ghc-options="+RTS -K64m -RTS". -K64m даёт 64MB стека.

  2. Если OOM — добавьте -A128m для аллокатора.

  3. В коде оптимизируйте: используйте strict fields в data или bang-patterns для Map.

  4. Тестируйте на малом модуле: не на полном примере, а на мини-файле.

В репозитории такие проблемы отмечены для больших файлов. Работает? Да, но следите за 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

Соберём всё:

  1. git clone https://github.com/alanz/ghc-exactprint && cd ghc-exactprint

  2. Установите GHC 9.14.1: ghcup install ghc 9.14.1 && ghcup set ghc 9.14.1

  3. cabal update && cabal configure

  4. Отредактируйте ghc-exactprint.cabal: добавьте executable как выше.

  5. В examples/InsertSignature.hs: pragma RankNTypes/AllowAmbiguousTypes, мигрируйте импорты, Ann → AnnD, AnnoMap с forall.

Пример фикса addSignature:

haskell
{-# LANGUAGE RankNTypes, AllowAmbiguousTypes #-}
import GHC.Hs
import GHC.Types.Anno (Anno)

addSig :: ... -> (forall ann. Anno ann => ann -> ann) -> ...
  1. cabal build insert-signature --ghc-options="+RTS -K64m -RTS"

  2. Запуск: cabal run insert-signature -- input.hs output.hs

Готово. Если краш — debug в ghci: :l InsertSignature.hs.

Этот гайд из практики Stack Overflow и репозитория.


Источники

  1. Stack Overflow — Решение проблем компиляции InsertSignature в ghc-exactprint с миграциями и стек-оверфлоу: https://stackoverflow.com/questions/79897781/how-do-i-compile-the-insertsignature-example-from-ghc-exactprint
  2. ghc-exactprint GitHub — Репозиторий с примерами, обновлениями для GHC 9+ и документацией: https://github.com/alanz/ghc-exactprint
  3. Hackage ghc-exactprint — Официальная страница пакета с поддержкой GHC 9.14 и зависимостями: https://hackage.haskell.org/package/ghc-exactprint
  4. Examples directory — Директория с исходниками InsertSignature.hs для адаптации: https://github.com/alanz/ghc-exactprint/tree/master/examples
  5. 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. Тестируйте на малом, читайте репозиторий — и ваш рефакторинг взлетит. Если застряли, форумы в помощь.

E

Пример InsertSignature из библиотеки ghc-exactprint не включён в ghc-exactprint.cabal как executable. Добавьте секцию с hs-source-dirs: examples и build-depends: base, ghc-exactprint, containers, ghc.

В ghc haskell мигрируйте импорты: HsSynGHC.Hs, RdrNameGHC.Types.Name.Reader, SrcLocGHC.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.

@alanz / Разработчик Haskell

Библиотека 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.

A

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.

@alanz / Разработчик Haskell

Директория examples содержит InsertSignature.hs для демонстрации ghc-exactprint в haskell.

Код требует обновления под GHC 9+ (импорты, AnnD, Anno).

Добавьте executable в cabal для haskell cabal build, но учтите полиморфизм типов и stack overflow в ghc 9.14.1.

@alanz / Разработчик Haskell

Исходный код InsertSignature.hs в ghc-exactprint использует устаревшие HsSyn.Anns и Ann — мигрируйте на GHC.Hs.AnnD и полиморфный GHC.Anno для ghc haskell 9.14.1.

Функции addSignature/addSignature2 нуждаются в RankNTypes.

При cabal build добавьте зависимости и GHC-Options для stack space overflow.

Авторы
E
Разработчик
@alanz / Разработчик Haskell
Разработчик Haskell
A
Maintainer Haskell-пакетов
P
Разработчик Haskell
M
Разработчик Haskell
Проверено модерацией
НейроОтветы
Модерация
Как скомпилировать InsertSignature в ghc-exactprint с GHC 9.14.1