В настоящее время я экспериментирую с разделением частично примененных функций. Чтобы сделать общий доступ видимым, я использую эффект трассировки. Чтобы проиллюстрировать мою проблему, я сначала показываю упрощенный пример .
f1, f2, f3, f4 :: Int -> Int
f1 = \x -> trace "f1" 0 + x
f2 x = trace "f2" 0 + x
f3 = (trace "f3" 0 +)
f4 = (+) (trace "f4" 0)
Я сравниваю эти функции в следующем сценарии, где f1
заменяется различными функциями.
apply :: (Int -> Int) -> (Int -> Int) -> Int
apply f g = f 42 + g 42
result = let f = f1
in apply f f
Вывод (скомпилированный без оптимизации) выглядит следующим образом.
f1 f1 f2 f2 f3 f4 336
Код ядра показывает, что и f1
, и f2
являются лямбда-функциями, тогда как f3
иf4
- частично примененные функции. В первом случае, по-видимому, нет разделения аргумента в теле лямбды, в то время как во втором случае это работает. Включение оптимизации компилятора приводит к совместному использованию для всех определений, но меня интересует, почему нет разделения в лямбда-функциях.