В 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-й элемент, который еще не существует? Я бы ожидал исключения, хотя и не бесконечный цикл...