在 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。其他编译器,如果它们存在一段时间,可能会有不同的行为。)
我想在不应用函数的情况下将其计算为其正常形式,例如,
\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。其他编译器,如果它们存在一段时间,可能会有不同的行为。)