В Haskell вы можете создавать бесконечные списки из-за лень:
Prelude> let g = 4 : g
Prelude> g !! 0
4
Prelude> take 10 g
[4,4,4,4,4,4,4,4,4,4]
Теперь, что именно происходит, когда я пытаюсь построить такой список?
Prelude> let f = f !! 10 : f
Prelude> f !! 0
Interrupted.
Prelude> take 10 f
[Interrupted.
Prelude>
Interrupted.
Я нажимаю CTRL + C после ожидания нескольких секунд. Кажется, он входит в бесконечный цикл, но почему это так?
Объяснение для не-Haskellers:
Оператор :
prepend
:
Prelude> 4 : [1, 2, 3]
[4,1,2,3]
Эта строка:
Prelude> let g = 4 : g
говорит: "Пусть g
- список, построенный путем добавления 4
в список g
". Когда вы запрашиваете первый элемент, возвращается 4, так как он уже существует. Когда вы запрашиваете второй элемент, он ищет элемент после 4. Этот элемент будет первым элементом списка g
, который мы только что вычислили (4), поэтому возвращается 4
. Следующий элемент - это второй элемент g
, который мы снова просто вычислили и т.д.
!!
просто индексируется в список, поэтому это означает, что элемент в индексе 0
из g
:
Prelude> g !! 0
4
Но когда я это делаю:
Prelude> let f = f !! 10 : f
что-то ломается, потому что для вычисления первого элемента f
вам нужен 11-й элемент, который еще не существует? Я бы ожидал исключения, хотя и не бесконечный цикл...