к
print (b :: [Int])
Size: a a a
к
print (b :: [Int])
NI
IO
b
с c
на топлевеле, так что даже первый вызов c
не дает трейса. С -fno-cse
все встает на свои места.IO
MK
MK
IO
c :: () -> [Int]
кстати все не так просто как мне казалось. Я сначала заменил там [1..5]
, которое в примере @kana_sama было, на [1,2]
, чтобы вывода поменьше было, и тогда трейс действительно только один раз вычислялся, но если написать [1..2]
станет вычисляться дважды. Насколько я понял из кора, при [1,2]
гхц выносит на топлевел _1 = trace "1" 1; _2 = trace "2" 2
и работает уже с ними, а с [1..2]
ничего такого не происходит, c
инлайнится дважды, на топлевеле получаются две(!) копии c
(cse отключен поэтому их не соединяет), каждая из которых трейсит. C NOINLINE все опять меморизуется. Так что да, мораль - бойтесь unsafePerformIOIO
c_worker = ...
c_body = c_worker 1#
c = \() -> c_body
show c_body
, а при фмапе похоже каждый принт инлайнит c
еще до того как появился c_body
, и уже от каждой этой копии получиться своя копия воркера. Так что тут дело именно в инлайне, версия с фмапом похоже достаточно дешевая чтобы гхц заинлайнил сразу, а компрехеншен нет.A
DB
С
DB
G
flip (.)
в виде оператора, если есть <&>
в Data.Functor (base), к примеру?G
AS
AS
С