Подтвердить что ты не робот

Что делает "пусть 5 = 10"? Разве это не операция присваивания?

Если я говорю let 5 = 10, почему 5 + 1 возвращает 6 вместо 11?

4b9b3361

Ответ 1

Когда вы говорите

let 5 = 10

это не переопределение 5, это сопоставление с образцом, то же самое происходит, когда вы говорите

foo 5 = undefined
 ... foo 10 ...

Образец просто терпит неудачу, если он когда-либо сопоставляется.

В let-выражениях матч ленив. Это означает, что совпадение выполняется только при оценке переменной, связанной с ней. Это позволяет нам писать такие вещи, как

 let foo = undefined in 10

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

Возможно, такие шаблоны без переменных не имеют смысла в let-bindings и должны быть обнаружены компилятором, но язык не запрещает их.

Ответ 2

В принципе,

let 5 = 10 in ...

эквивалентно

case 10 of ~5 -> ...

Обратите внимание на ~, который обозначает ленивый или неопровержимый шаблон. Это шаблон, который соответствует всем, и откладывает соответствие до точки, в которой действительно требуется какая-либо переменная. В шаблоне 5 нет переменных, поэтому ничего не происходит.

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

Чтобы прояснить смысл ленивых шаблонов, рассмотрите это:

case f 3 of
  (x,y) -> g 10 x y

здесь f 3 сначала оценивается (WHNF), выставляя конструктор пары. Тогда x,y привязаны к (еще не оцененным) компонентам пары. Наконец, вычисляется g 10, результат применяется к x (который может потребоваться сейчас), а затем к y (что может потребовать запроса x или y).

Для сравнения,

case f 3 of
  ~(x,y) -> g 10 x y

не начинается с оценки f 3. Вместо этого x привязан к неоцененному fst (f 3) и y привязан к неоцененному snd (f 3). Вместо этого мы начинаем с оценки g 10. Затем мы применяем это к x: это может вызвать запрос x, вызывая оценку f 3. Затем мы применяем результат к y, вызывая аналогичную оценку. Большинство реализаций фактически разделяют результат f 3 между x и y, так что он вычисляется не более одного раза.

Ответ 3

Как @n.m. говорит, что вы образец соответствия. Вот несколько примеров.

Соответствие шаблонов может быть успешным

Prelude> let (a, 10) = (15, 10) in a
15

или сбой.

Prelude> let (a, 10) = (15, 15) in a
*** Exception: <interactive>:5:5-22: Irrefutable pattern failed for pattern (a, 10)

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

Prelude> let (a, 10) = (15, 15) in "Something else"
"Something else"

Обратите внимание, что типы все еще должны проверять:

Prelude> let (a, 10, 999) = (15, 15) in "Something else"

<interactive>:7:20: error:
    • Couldn't match expected type ‘(t, Integer, Integer)’
                  with actual type ‘(Integer, Integer)’
    • In the expression: (15, 15)
      In a pattern binding: (a, 10, 999) = (15, 15)
      In the expression: let (a, 10, 999) = (15, 15) in "Something else"
    • Relevant bindings include a :: t (bound at <interactive>:7:6)