Какой тип области видимости использует Haskell?

StackOverflow https://stackoverflow.com/questions/333185

  •  22-07-2019
  •  | 
  •  

Вопрос

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

let x = 10

затем определите функцию

let square x = x*x

У вас есть 2 разных "x", и означает ли это, что он имеет динамическую область видимости?Если нет, то какую область видимости он использует и почему?

Кроме того, могут ли переменные Haskell иметь псевдонимы (другое имя для одной и той же ячейки памяти / значения)?

Спасибо.

Это было полезно?

Решение

Что-то в ваших высказываниях не так...

  • В Haskell нет изменяемых переменных, только определения (или неизменяемые переменные).
  • Переменная ячейка памяти — это концепция, которой нет в Haskell.

В вашем примере Икс является нет 10 в функции — это просто аргумент квадрата, который может принимать любое значение (тип можно указать позже), в данном случае 10, но только в этом случае.

Вот пример псевдонимов, предоставленных Курт Сэмпсон:

import Data.IORef

main :: IO ()
main = do x <- newIORef 0         -- write 0 into x
          readIORef x >>= print   -- x contains 0
          let y = x
          readIORef y >>= print   -- y contains 0
          writeIORef x 42         -- write 42 into x
          readIORef y >>= print   -- y contains 42

Другие советы

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

например.

x = 10

Приводит к значению, на которое ссылается x в глобальном масштабе, тогда как

square x = x * x

приведет к x будучи лексически ограниченным до функционального квадрата.Это может помочь, если вы подумаете о том, что приведенная выше форма является синтаксической тонкостью для:

square = \ x -> x * x

Что касается вашего другого вопроса, я не уверен, что вы подразумеваете под псевдонимами

Отвечая только на вторую часть вопроса:

Вы можете иметь несколько псевдонимов для одной и той же «ячейки памяти», но, поскольку все они неизменяемы, в большинстве случаев это не имеет значения.

Тупой пример:

foo x y = x * y
bar z = foo z z

Когда внутри foo звонили из bar, оба x и y явно имеют одно и то же значение.Но поскольку вы не можете изменить ни x или y, вы даже не заметите.

Поскольку на первую часть вопроса уже ответили другие, вот вторая часть:

Я предполагаю, что aliasing ты имеешь в виду one name for another.Поскольку Haskell — функциональный язык, а функции в любом случае ведут себя как обычные идентификаторы, вы можете сделать это следующим образом:

y = x

который будет определять псевдоним y для функции x.Обратите внимание, что все является функцией.Даже если это похоже на "переменная", это просто нулевая функция, не принимающая аргументов.Псевдонимы типов выглядят следующим образом:

type Function = Double -> Double

который будет определять псевдоним Function для типа Double -> Double

Haskell использует статические вложенные области видимости.Что немного сбивает с толку по сравнению с другими языками, имеющими статические вложенные области видимости, так это то, что областью действия имени является блок, включающий тесты, предшествующие его определению..Например

evens = 0 : map (+1) odds
odds  = map : (+1) evens

здесь слово «шансы» входит в определение «четов», несмотря на тот удивительный факт, что «шансы» еще не определены.(В примере определяются два бесконечных списка четных и нечетных чисел.)

Мертвым языком с аналогичным правилом области видимости была Modula-3.Но Haskell немного сложнее: вы можете попытаться «переопределить» переменную в той же области, но вместо этого вы просто вводите другое уравнение рекурсии.Это ловушка для людей, которые впервые изучили ML или Scheme:

let x = 2 * n
    x = x + 1   -- watch out!

Это совершенно хороший ML или Scheme let*, но Haskel имеет семантику Scheme letrec без ограничений на значения лямбда.Неудивительно, что это сложная штука!

В вашем примере глобальное определение x затеняется локальным определением x.В Haskell область видимости переменной определяется статическим чтением исходного кода — это называется лексической областью видимости, но можно получить что-то похожее на динамическую область видимости с неявными параметрами (но это может привести к некоторому неожиданному поведению (я читал;сам никогда не пробовал)).

Подводя итог другим ответам кратко:

  1. лексическая область видимости
  2. псевдонимы — это так же просто, как x = 1; y = x но обычно это не имеет значения, потому что вещи неизменны.

А let синтаксис, который вы используете в своем примере, выглядит так, как будто он находится в интерактивном ghci> быстрый.Все в интерактивном режиме происходит внутри монады ввода-вывода, поэтому там все может оказаться более изменчивым, чем обычно.

Ну, как я думаю, люди уже сказали, что в Haskell нет переменных, которые есть в большинстве других языков, в нем есть только выражения.В вашем примере let x = 10 x — это выражение, которое всегда оценивается как 10.Фактически вы не сможете изменить значение x позже, хотя вы можете использовать правила области видимости, чтобы скрыть его, определив x как другое выражение.

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

import Data.IORef

main :: IO ()
main = do x <- newIORef 0         -- write 0 into x
          readIORef x >>= print   -- x contains 0
          let y = x
          readIORef y >>= print   -- y contains 0
          writeIORef x 42         -- write 42 into x
          readIORef y >>= print   -- y contains 42
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top