В Haskell почему строка cmd GHCi позволяет мне изменять значение переменной, что недопустимо при загрузке из текстового файла - PullRequest
1 голос
/ 21 сентября 2019

Я могу сделать следующее в GHCi, что, как я понимаю, не должно быть возможным в Haskell:

Prelude> myPi = 3.14
Prelude> myPi = 4
Prelude> myPi
4

Но если я помещу это в файл, это выдаст мне ошибку

-- main.hs
myPi = 3.14
myPi = 4
Prelude> :l main.hs
main.hs:2:1: error:
    Multiple declarations of ‘myPi’
    Declared at: main.hs:1:1
                 main.hs:2:1

Что делает GHCi, чтобы позволить мне 'redeclare' переменные.Есть ли способ остановить это?

Ответы [ 2 ]

8 голосов
/ 21 сентября 2019

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

Prelude> let myPi = 3.14
Prelude> let f x = x + myPi
Prelude> let myPi = 4
Prelude> f 0
3.14
6 голосов
/ 21 сентября 2019

Я могу сделать следующее в GHCi, что, как я понимаю, не должно быть возможным в Haskell

Prelude> myPi = 3.14
Prelude> myPi = 4
Prelude> myPi

В ghci вы в основном работаете в "неявном" do.И интерпретатор добавит к нему неявное значение let.

Таким образом, вы написали эквивалент:

main = do
    let myPi = 3.14
    let myPi = 4
    print myPi

Если мы десугарируем нотацию do, мы получим:

main = let myPi = 3.14 in (let myPi = 4 in print myPi)

То, что мы здесь сделали, - это построение двух разных переменных, которые имеют одно и то же имя.let определяет область действия, и, таким образом, в вашем print myPi он принимает переменные, которые имеют ближайшую область действия, поэтому вторая переменная.

Но за пределами внутреннего let … in … все еще существует myPi переменная со значением 3.14.Таким образом, вы не изменили значение myPi.

Если мы, например, напишем:

main = do
    let myPi = 3.14
    let myPi = 4 in print myPi
    print myPi

Сначала будет напечатано 4 (из внутреннегоmyPi), а затем 3.14 (из внешнего myPi).

...