在 Haskell 中未实际应用的规范化函数

Normalizing functions without actually applying it in Haskell

我想在不应用函数的情况下将其计算为其正常形式,例如,

\n -> n + sum [1..100]

应评估为

\n -> n + 5050

但是函数没有NFData实例,这是合理的,因为我们无法获得函数的子项。

我想知道是否有可能借助一些编译器魔法来完全规范化一个函数。

不,这是不可能的。但是,在大多数情况下,它是不需要的。我怀疑你错过的技巧是通过 let 提升不依赖于输出的昂贵计算。比较:

-- recomputes `sum [1..100]` each time you apply it to an argument
f1 :: Int -> Int
f1 n = n + sum [1..100]

-- computes `sum [1..100]` just once, then uses the "cached" result each time
-- you apply it to an argument
f2 :: Int -> Int
f2 = let s = sum [1..100] in \n -> n + s

函数 f1 每次使用都很昂贵。函数 f2 第一次使用时很昂贵,但以后每次都很便宜。

(此答案特定于 GHC。其他编译器,如果它们存在一段时间,可能会有不同的行为。)