LINUX.ORG.RU

История изменений

Исправление 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]]

тут мы видим когда в новом списке реально форсятся вычисления, для более полноценной картины надо бы написать свой ++ в доп дебагом, чтобы увидеть когда какой элемент форсится.