Переназначение в ghci - PullRequest
1 голос
/ 13 апреля 2020

Возможно ли переназначить одну и ту же переменную в ghci? Конечно, это невозможно в обычном Haskell (по крайней мере, без чего-то вроде IORef), но мне было любопытно, потому что переменная it в ghci, которую вы получаете, включив опцию :m. С этим включением я получаю опыт, когда it эффективно переназначается с помощью , а не , связывая следующее выражение с чем-либо, например,

λ> 1 + 1
2
it :: Num a => a
λ> it
2
it :: Num a => a
λ> it + 1
3
it :: Num a => a
λ> it
3
it :: Num a => a

Есть ли способ реализовать тот же эффект для произвольная именованная переменная, а не просто специальная it?

1 Ответ

6 голосов
/ 13 апреля 2020

Каждая новая строка в GHCi входит в новую вложенную область видимости. Рассмотрим

> x = 1
> x
1
> foo y = x + y
> foo 41
42
> x = 7                 -- new x
> x
7
> bar y = x + y         -- refers to new x
> bar 41
48
> foo 41                -- still refers to the same old x binding
42

Вторая привязка x определяет новую переменную с тем же именем.

Естественно, это затеняет предыдущую привязку для этого имени, что делает его недоступным само по себе. Любая другая сущность (например, foo), которая ссылалась на нее ранее, будет продолжать хранить эту ссылку , независимо от того, затеняется ли более новая вложенная среда.

Это следует принципу неизменности значений в Haskell: foo остается неизменным.

Одно предупреждение:

> :{
  x = 1
  foo y = x + y
  x = 7                   -- error: conflicting definition
  bar y = x + y
  :}

вызывает ошибку, потому что строки, введенные в многострочном режиме, принадлежат одной и той же области видимости.

Другими словами, ответ на ваш вопрос нет , это нарушит фундаментальные свойства чистоты Haskell.

it также не переназначается, он определяется заново в каждой новой вложенной среде, когда есть какой-либо выход, связанный с выходным значением:

> x
7
> it
7
> it_2                       -- made a typo

error: Not in scope: `it_2'
> it+2                       -- no previous output, same `it` in effect
9
> it+2                       -- most recent `it` is 9
11

Итак вы всегда можете скрыть свою переменную и создать новую привязку с тем же именем, но вы не можете изменить старую привязку, потому что она теперь является частью истории, и прошлое не может быть изменено, определение. Это уже произошло .

Или вы можете создать свой собственный интерпретатор Haskell, где вы дадите пользователю возможность «изменить» старую привязку, но что на самом деле случается, что новая копия интерпретатора будет порождена, даже «воспроизводя» все записанные действия пользователя по запросу - новые определения и все - с этого момента. Тогда пользователь получит измененную копию, которая не заметит существование первой. Вы даже можете убить оригинал в этот момент. Может ли это считаться тем, что пользователь изменил прошлое? Прошлое пользователя не изменилось, его время идет вперед. Прошлое нового экземпляра всегда было тем, чем оно является сейчас, что касается it . Старый оригинал (копия?) Исчез ... Вопрос для размышления.

...