Почему GHCi понимает импорт, а GHC - нет? - PullRequest
4 голосов
/ 20 апреля 2019

Я довольно новичок в Хаскеле и думаю, что у меня где-то есть фундаментальное недоразумение. Когда я в GHCi (использую команду ghci), я могу набрать import System.Random, и это работает. Затем я могу генерировать случайные числа.

Затем я создаю файл с именем test.hs, который содержит только одну строку: import System.Random. Затем я вызываю команду ghc test.hs и получаю следующее сообщение об ошибке:

test.hs:1:1: error:
    Could not find module ‘System.Random’
    There are files missing in the ‘random-1.1’ package,
    try running 'ghc-pkg check'.
    Use -v to see a list of the files searched for.
  |
1 | import System.Random
  | ^^^^^^^^^^^^^^^^^^^^

Однако, если я вернусь в GHCi, я могу набрать :load test.hs. Это работает и позволяет мне генерировать случайные числа.

Когда я запускаю ghc-pkg check, я получаю только предупреждения об отсутствующих файлах интерфейса пикши: https://pastebin.com/6a9f0nYZ. Насколько я понимаю, это не связано с текущей проблемой.

Кроме того, когда я запускаю ghc-pkg list, random-1.1 находится в списке, поэтому random должен быть установлен.

Пара вопросов:

  • Почему GHC и GHCi имеют доступ к различным импортам? Почему система настроена таким образом? Может быть, я просто не понимаю отношения между GHC и GHCi.
  • Согласно сообщению об ошибке, «отсутствуют файлы». Как я могу выяснить, какие файлы?
  • Как я могу сделать так, чтобы я мог компилировать файлы на Haskell, которые используют System.Random?

Редактировать: GHC и GHCi имеют одинаковую версию.

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.6.4
$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.6.4

Редактировать: ghc и ghci находятся в / usr / bin /

$ which ghc
/usr/bin/ghc
$ which ghci
/usr/bin/ghci

1 Ответ

2 голосов
/ 21 апреля 2019

Обновление: Похоже, что это особенность Arch Linux, а не поврежденный пакет.Я обновил свой ответ соответственно.

GHCi загружает «динамические» версии модулей.По умолчанию GHC связывается со «статическими» версиями модулей.В частности, когда вы запускаете:

> import System.Random

в GHCi, он пытается получить доступ к файлу Random.dyn_hi, чтобы получить информацию об интерфейсе для модуля.Напротив, когда вы компилируете файл с этим оператором импорта, GHC пытается получить доступ к файлу Random.hi.

. Чтобы убедиться, что это проблема, запустите ghc-pkg field random import-dirs и просмотрите итоговый каталог.Подкаталог System должен содержать два файла: System.hi и System.dyn_hi.Если первое отсутствует, это ваша проблема.

Теперь, похоже, вы, вероятно, используете Arch Linux.Как описано на вики-странице Arch Haskell в разделе "Проблемы со связыванием", пакеты сообщества Arch Haskell (включая haskell-random) намеренно опускают статические версии файлов интерфейса и библиотек.

Есть несколько способов решения этой проблемы:

  • Вы можете использовать динамическое связывание при компиляции с GHC.При непосредственном использовании GHC это просто означает пропуск флага -dynamic.Для проектов на основе Cabal на этой странице приведены инструкции по изменению ~/.cabal/config для использования динамического связывания для всех проектов.
  • Вы можете установить пакеты ghc-static и ghc-pristine и настроить свой путь и/ или Cabal для использования компилятора в /usr/share/ghc-pristine/bin/ghc, который будет поддерживать свою собственную отдельную базу данных пакетов, которая не будет мешать глобально установленным пакетам сообщества Haskell, например haskell-random.
  • . Вы можете установить ghc-static, чтобы получитьстатические версии базовых библиотек и затем запустите cabal install --force-reinstalls somepackage для всех не базовых пакетов, которые вам нужны.Обратите внимание, что вики отмечает, что это может быть утомительным и сложным, так как вы должны вручную определить все зависимости пакета.

Теперь, похоже, у вас уже установлена ​​ghc-static или при вызове GHCвы бы также получили ошибку об отсутствующих файлах в пакете base.Вы запустили cabal install --force-reinstalls random, хотя, как отмечает @dfeuer, было бы безопаснее запустить:

$ cabal install --force-reinstalls random-1.1

, чтобы гарантировать, что эта же версия была переустановлена.

В любом случае, это установило дополнительнуюкопия random в вашем пользовательском каталоге пакета.Если вы запустите:

$ ghc-pkg list

, вы увидите, что random-1.1 указан как в глобальной базе данных, так и в базе данных пользователей:

/usr/lib/ghc-8.6.4/package.conf.d
    ...
    random-1.1
    ...
/home/xxxx/.ghc/x86_64-linux-8.6.4/package.conf.d
    random-1.1

, а если вы запустите:

$ ghc-pkg describe random

вы увидите, что в нем перечислены две отдельные установленные версии, поэтому вы теперь получаете дубликаты полей с ghc-pkg field random import-dirs.

В этом не должно быть ничего плохого.Ваша пользовательская база данных будет иметь приоритет над глобальной базой данных, поэтому ваша новая установленная версия random будет использоваться при запуске GHCi или GHC.

Обратите внимание, что если вы передумаете и захотите отказаться от этогопереустановка (и, возможно, попробуйте одно из других решений, предложенных в вики), вы должны иметь возможность запустить:

$ ghc-pkg unregister --user random

Технически, это фактически не удалит пакет (так как скомпилированная версия все равно будеттам под ~/.cabal/lib), но в противном случае все должно вернуться на свои места.

...