Почему: спринт всегда печатает "_"?

Prelude> let a = 3
Prelude> :sprint a
a = _
Prelude> let c = "ab"
Prelude> :sprint c
c = _

Почему он всегда печатает _? Я не совсем понимаю семантику команды :sprint.

Ответ 1

Haskell - ленивый язык. Он не оценивает результаты, пока они не "нужны".

Теперь просто печать значения заставляет все это "нужно". Другими словами, если вы наберете выражение в GHCi, он попытается распечатать результат, который заставит все это оценивать. Обычно это то, что вы хотите.

Команда sprint (которая является функцией GHCi, а не частью языка Haskell) позволяет вам узнать, сколько из этого значения было оценено в этот момент.

Например:

Prelude> let xs = [1..]
Prelude> :sprint xs
xs = _

Итак, мы просто объявили xs, и в настоящее время он не оценен. Теперь отпечатайте первый элемент:

Prelude> head xs
1
Prelude> :sprint xs
xs = 1 : _

Теперь GHCi оценил заголовок списка, но не более того.

Prelude> take 10 xs
[1,2,3,4,5,6,7,8,9,10]
Prelude> :sprint xs
xs = 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : _

Теперь оцениваются первые 10 элементов, но больше остаются. (Так как xs - бесконечный список, это не удивительно.)

Вы можете создавать другие выражения и оценивать их понемногу, чтобы узнать, что происходит. Это действительно часть отладчика GHCi, который позволяет вам проходить свой код по одному бит за раз. Особенно, если ваш код попадает в бесконечный цикл, вы не хотите ничего print, потому что это может заблокировать GHCi. Но вы все еще хотите увидеть, что происходит... следовательно sprint, который позволяет вам видеть, что оценивалось до сих пор.

Ответ 2

Хаскелл ленив. Он не оценивает вещи, пока они не понадобятся.

Команда GHCi sprint (а не часть Haskell, только команда отладки интерпретатора) печатает значение выражения без принудительной оценки.

Когда вы пишете

let a = 3

вы привязываете новое имя a к правильному выражению, но Haskell пока не оценит эту вещь. Поэтому, когда вы sprint, оно печатает _ как значение, указывающее, что выражение еще не было оценено.

Попробуйте следующее:

let a = 3
:sprint a -- a has not been evaluated yet
print a -- forces evaluation of a
:sprint a -- now a has been evaluated

Ответ 3

Я немного опаздываю, но у меня была аналогичная проблема:

λ: let xs = [1,2,3]
xs :: Num t => [t]
λ: :sprint xs
xs = _
λ: print xs
λ: :sprint xs
xs = _

Эта проблема специфична для полиморфных значений. Если у вас включен -XNoMonomorphismRestriction, ghci никогда не будет оценивать /force xs, он будет оценивать только/специализации:

λ: :set -XMonomorphismRestriction
λ: let xs = [1,2,3]
xs :: [Integer]
λ: print xs
λ: :sprint xs
xs = [1,2,3]