Сколько из этого треугольника Паскаля это оценивает?

Если у меня есть эта константа pascal, определенная как

pascal :: [[Int]]
pascal = iterate newrow [1]
  where newrow = (zipWith (+) <*> tail) . ([0]++) . (++[0])

И я оцениваю pascal !! 50 !! 50 в GHCI, сколько из этого треугольника это эвальствует? Означает ли эта лента только нужные значения (плюс куча гроздей)?

Ответы

Ответ 1

Да, оцениваются только те элементы, которые необходимы для вычисления рассматриваемого элемента.

GHCi предлагает команды отладки :sprint и :print, которые могут дать вам некоторую информацию о том, какие части значения уже были оценены.

В этом примере:

GHCi> :sprint pascal
pascal = _

(Это потому, что в этот момент ничего не было оценено, а thunks показаны как _.)

GHCi> pascal !! 5 !! 5
1

(Я не использую 50, потому что тогда этот пример станет слишком длинным.)

GHCi> :sprint pascal
pascal = [1] : [_,1] : [_,_,1] : [_,_,_,1] : [_,_,_,_,1] :
         (_ : _ : _ : _ : _ : 1 : _) : _

Теперь вы получаете довольно четкое представление о том, какие части были просмотрены.

Попробуйте еще одно:

GHCi> pascal !! 5 !! 4
5
GHCi> :sprint pascal
pascal = [1] : [1,1] : [_,2,1] : [_,_,3,1] : [_,_,_,4,1] :
         (_ : _ : _ : _ : 5 : 1 : _) : _

И еще один:

GHCi> pascal !! 10 !! 5
252
GHCi> :sprint pascal
pascal = [1] : [1,1] : [1,2,1] : [1,3,3,1] : [1,4,6,4,1] :
         (1 : 5 : 10 : 10 :   5 :   1 : _) :
         (_ : 6 : 15 : 20 :  15 :   6 : _) :
         (_ : _ : 21 : 35 :  35 :  21 : _) : 
         (_ : _ : _  : 56 :  70 :  56 : _) :
         (_ : _ : _  : _  : 126 : 126 : _) : 
         (_ : _ : _  : _  : _   : 252 : _) : _