История изменений
Исправление qnikst, (текущая версия) :
Рассмотрим реализацию через Prelude:
[]++ys=ys
(x:xs) ++ ys = x : (xs ++ ys)
let a = 1:2:3:Null
let b = 4:5:6:Null
let c = a ++ b = (++) (1:{2:..}) (4:{5:..}) =
= 1: (++) ((++) (2:...) (4:...)) =
/здесь 1 уже новый список остальное ссылки на старые старые/
/то, что после : это отложенное вычисление/
= далее раскручиваем список таким же образом, если он нам нужен.
можно попробовать в интерпретаторе:
Prelude Data.List Debug.HTrace> :m Data.List Debug.HTrace
Prelude Data.List Debug.HTrace> let a = map (\x -> htrace ("<"++show x++">") x) [1..2]
-- htrace будет выводить значение x когда оно будет вычисляться
Prelude Data.List Debug.HTrace> let b = map (\x -> htrace ("<"++show x++">") x) [3..4]
Prelude Data.List Debug.HTrace> let c = a++b
-- на этом моменте у нас все списки в WHNF и ни один их элемент не вычислен, попробуем рассмотреть inits c
-- т.е. список голов списка c и посмотреть, когда вызываются вычисления
> inits c[br][/quote][[],[<1>
1],[1,<2>
2],[1,2,<3>
3],[1,2,3,<4>
4]]
тут мы видим когда в новом списке реально форсятся вычисления, для более полноценной картины надо бы написать свой ++ в доп дебагом, чтобы увидеть когда какой элемент форсится.
Исправление qnikst, :
Рассмотрим реализацию через Prelude:
[]++ys=ys
(x:xs) ++ ys = x : (xs ++ ys)
let a = 1:2:3:Null
let b = 4:5:6:Null
let c = a ++ b = (++) (1:{2:..}) (4:{3:..}) =
= 1: (++) ((++) (2:...) (4:...)) =
/здесь 1 уже новый список остальное старые/
/дальше раскручиваем список тем же образом/
можно попробовать в интерпретаторе: Prelude Data.List Debug.HTrace> :m Data.List Debug.HTrace Prelude Data.List Debug.HTrace> let a = map (\x -> htrace («<»++show x++«>») x) [1..2] -- htrace будет выводить значение x когда оно будет вычисляться Prelude Data.List Debug.HTrace> let b = map (\x -> htrace («<»++show x++«>») x) [3..4] Prelude Data.List Debug.HTrace> let c = a++b -- на этом моменте у нас все списки в WHNF и ни один их элемент не вычислен, попробуем рассмотреть inits c -- т.е. список голов списка c и посмотреть, когда вызываются вычисления
inits c
[[],[<1> 1],[1,<2> 2],[1,2,<3> 3],[1,2,3,<4> 4]]
тут мы видим когда в новом списке реально форсятся вычисления, для более полноценной картины надо бы написать свой ++ в доп дебагом, чтобы увидеть когда какой элемент форсится.
Исходная версия qnikst, :
Рассмотрим реализацию через Prelude: [data] []++ys=ys (x:xs) ++ ys = x : (xs ++ ys)
let a = 1:2:3:Null let b = 4:5:6:Null let c = a ++ b = (++) (1:{2:..}) (4:{3:..}) = = 1: (++) ((++) (2:...) (4:...)) = /здесь 1 уже новый список остальное старые/ /дальше раскручиваем список тем же образом/
можно попробовать в интерпретаторе: Prelude Data.List Debug.HTrace> :m Data.List Debug.HTrace Prelude Data.List Debug.HTrace> let a = map (\x -> htrace («<»++show x++«>») x) [1..2] -- htrace будет выводить значение x когда оно будет вычисляться Prelude Data.List Debug.HTrace> let b = map (\x -> htrace («<»++show x++«>») x) [3..4] Prelude Data.List Debug.HTrace> let c = a++b -- на этом моменте у нас все списки в WHNF и ни один их элемент не вычислен, попробуем рассмотреть inits c -- т.е. список голов списка c и посмотреть, когда вызываются вычисления
inits c
[[],[<1> 1],[1,<2> 2],[1,2,<3> 3],[1,2,3,<4> 4]]
тут мы видим когда в новом списке реально форсятся вычисления, для более полноценной картины надо бы написать свой ++ в доп дебагом, чтобы увидеть когда какой элемент форсится.