загрузка скрипта .hs в интерпретатор - PullRequest
2 голосов
/ 25 января 2012

В Haskell ghci я попытался

Prelude> :load filename.hs
Ok, modules loaded: Main.

, к сожалению, я не могу запустить ни одну из функций, определенных в файле.Я скомпилировал файл без каких-либо ошибок, но вызывающая функция выдает ошибку «Not in scope: (имя функции)».Странно то, что раньше у меня не было проблем с запуском этого ...

Ответы [ 5 ]

3 голосов
/ 25 января 2012

Проблема в том, что ваш редактор компилирует код с чем-то вроде

$ ghc foo.hs

Поскольку у вашего файла нет объявления модуля, GHC предполагает, что модуль называется Main, так как вы не делали 'не указывать иначе и, поскольку он компилирует полную программу, не экспортирует любое из определений, кроме main;то есть он действует так, как если бы у вас было объявление модуля, например:

module Main (main) where

, тогда как GHCi по умолчанию:

module Main where

Эти объявления модуля указывают имямодуль, который вы компилируете, и какие значения экспортируются.С первым объявлением из модуля экспортируется только main;во втором случае экспортируется каждое значение верхнего уровня.К значениям, которые не экспортируются, нельзя получить доступ из-за пределов модуля, поэтому в GHCi появляются ошибки «не в области действия».

Непоследовательное поведение GHCi, по-видимому, облегчает тестирование кода;вам не нужно иметь объявление модуля для загрузки файла и использования его определений.Решение состоит в том, чтобы поместить module Main where (или другое имя модуля) вверху вашего файла, который явно экспортирует все.Лично я думаю, что это поведение сбивает с толку, и поведение GHC и GHCi, вероятно, должно быть изменено, чтобы быть последовательным.

1 голос
/ 25 января 2012

Стандарт языка гласит, что если не дается объявление модуля, это неявно module Main (main) where. Когда исходные файлы Haskell скомпилированы и затем загружены в ghci, в область видимости попадают только экспортированные объекты рассматриваемого модуля. В вашем случае, без объявления модуля, это только функция main.

Однако, так как это довольно неудобно при разработке, ghci может загружать интерпретируемые модули с более широкой областью действия, ср. руководство пользователя . Модули, загруженные в этой форме, помечаются звездочкой перед именем модуля в приглашении, и для таких модулей не только каждый объект верхнего уровня, определенный в модуле, находится в области видимости, но также и импортированные объекты, все в области видимости вверху. Уровень модуля также доступен в приглашении ghci, когда модуль загружается в этой форме.

Это позволяет удобно тестировать функции в процессе разработки и, следовательно, является хорошей вещью ™. С другой стороны, как справедливо отмечает @ehird, разница в поведении может сбивать с толку и поэтому является плохой вещью.

В целом, я думаю, что преимущества более широкой области применения ghci для *Module s перевешивают несоответствие.

0 голосов
/ 26 января 2013

Не уверен, поможет ли это, но у меня была та же проблема.

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

Попытка загрузить файл выглядела так, как будто все получилось (Whither.hs, интерпретировано) - но я получил ту же ошибку.

0 голосов
/ 25 января 2012

Возможно, вы уже скомпилировали модуль, чтобы в каталоге находились файлы .o и .hi. Когда GHCi находит их, он по умолчанию загружает модуль в скомпилированном режиме, что означает, что в области видимости находится только материал, экспортированный из модуля.

Если вы не включили объявление модуля, по умолчанию это будет только main, поскольку объявление модуля по умолчанию - module Main (main) where. Отсюда и название Main.

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

Prelude> :load Foo.hs
[1 of 1] Compiling Main             ( Foo.hs, interpreted )
Ok, modules loaded: Main.
*Main> 

Звездочка перед Main означает, что модуль открыт в интерпретированном режиме и что все в нем находится в области видимости, включая содержимое, импортированное из других модулей. Однако, если бы я только что скомпилировал Foo.hs и затем попытался загрузить его в GHCi, я бы вместо этого увидел что-то вроде этого:

Prelude> :load Foo.hs
Ok, modules loaded: Main.
Prelude Main> 

Вы можете включить интерпретируемый режим, поставив перед именем файла звездочку:

Prelude> :load *Foo.hs
[1 of 1] Compiling Main             ( Foo.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
0 голосов
/ 25 января 2012

Трудно точно догадаться, в чем проблема.Вы изменили строку в верхней части файла с чего-то вроде:

module Main where

на что-то вроде:

module Main (main) where

Если бы вы это сделали, она бы экспортировала только функцию main.

...