Помните, что "foo"
это просто синтаксический сахар для 'f':'o':'o':[]
.
То есть String
это просто псевдоним для [Char]
, который представляет собой просто связанный список символов.
Когда клиентский код потребляет связанный список, он разлагает его обратно на голову и хвост (например, x:xs
), что-то делает с головой (при желании), а затем рекурсивно обращается к хвосту.
Когда ваш код создает связанный список, из-за ленивых вычислений все, что ему нужно сделать, это вернуть thunk или пообещать, что он вернет связанный списоккогда попросили.Когда разыменовывается голова, она предоставляется по требованию, а хвост остается в качестве обещания для остальной части списка.
Это должно быть легко увидеть, если список не скопирован или иным образомсохраненный, каждый блок будет использован один раз, а затем отброшен, так что общее пространство хранения будет постоянным.
Многие строгие языки предоставляют механизм (часто называемый generator ) для достижения того же видагенерации ленивых списков, но с ленивой оценкой такие функции «бесплатны» как часть языка - по сути, все списки на Haskell являются генераторами!