к
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
С