Какую область видимости использует Haskell? - PullRequest
6 голосов
/ 02 декабря 2008

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

let x = 10

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

let square x = x*x

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

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

Спасибо.

Ответы [ 9 ]

11 голосов
/ 02 декабря 2008

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

например.

x = 10

В результате значение в глобальной области видимости указывается через x, тогда как

square x = x * x

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

square = \ x -> x * x

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

6 голосов
/ 02 декабря 2008

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

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

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

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

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

6 голосов
/ 02 декабря 2008

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

  • В Haskell нет изменяемых переменных, только определения (или неизменяемые переменные)
  • Расположение переменной памяти - это концепция, которой нет в Haskell

В вашем примере x - это , а не 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
3 голосов
/ 02 декабря 2008

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

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

y = x

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

type Function = Double -> Double

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

2 голосов
/ 10 декабря 2008

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

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

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

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

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

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

2 голосов
/ 02 декабря 2008

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

1 голос
/ 03 декабря 2008

Чтобы кратко суммировать остальные ответы:

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

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

0 голосов
/ 15 июня 2009

Да, у 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
0 голосов
/ 07 декабря 2008

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

...