Какая область применения Haskell?

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

let x = 10

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

let square x = x*x

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

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

Спасибо.

Ответ 1

В ваших утверждениях есть некоторые вещи...

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

В вашем примере x не 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

Ответ 2

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

например.

x = 10

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

square x = x * x

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

square = \ x -> x * x

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

Ответ 3

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

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

Немой пример:

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

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

Ответ 4

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

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

y = x

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

type Function = Double -> Double

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

Ответ 5

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

Ответ 6

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

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

здесь имя "коэффициенты" находится в области определения "evens", несмотря на удивительный факт, что "коэффициенты" еще не определены. (Пример определяет два бесконечных списка четных и нечетных чисел.)

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

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

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

Ответ 7

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

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

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

Ответ 8

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

Ответ 9

Да, у 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