首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在纯Haskell中使用部分应用时,如何保证效率?

在纯Haskell中使用部分应用时,如何保证效率?
EN

Stack Overflow用户
提问于 2012-09-05 21:34:38
回答 1查看 219关注 0票数 7

我有一些代码,它的结构等同于:

代码语言:javascript
复制
import Debug.Trace

newtype SomeExpensiveHiddenType = SCHT Double

expensive :: Double -> Double -> SomeExpensiveHiddenType
expensive a b = SCHT $ trace "call expensive" (*) a b

cheap :: SomeExpensiveHiddenType -> Double -> Double
cheap (SCHT x) c = trace "call cheap" (+) x c

f1 :: Double -> Double -> Double -> Double
f1 a b c = let x = expensive a b in cheap x c

例如,f1是一个函数,它根据前两个参数计算代价高昂的结果,然后将其与第三个参数一起使用。我曾希望对前两个参数的部分应用程序,然后重复应用第三个参数,将导致昂贵的计算只运行一次。不幸的是,事实并非如此:

代码语言:javascript
复制
test1 = do
    putStrLn "test 1"
    let p = f1 2 3
    print (p 0.1)
    print (p 0.2)
    print (p 0.3)

结果如下:

代码语言:javascript
复制
*Main> test1
test 1
call cheap
call expensive
6.1
call cheap
call expensive
6.2
call cheap
call expensive
6.3
*Main> 

我想出了一个似乎是解决方案:

代码语言:javascript
复制
newtype X a = X { unX :: a }
f2 :: Double -> Double -> X (Double -> Double)
f2 a b = let x = expensive a b in X (cheap x)

test2 = do
    putStrLn "test 2"
    let p = unX $ f2 2 3
    print (p 0.1)
    print (p 0.2)
    print (p 0.3)

结果是:

代码语言:javascript
复制
*Main> test2
test 2
call cheap
call expensive
6.1
call cheap
6.2
call cheap
6.3
*Main> 

但这看起来相当混乱。有没有一种更干净的方法可以避免对昂贵的calc的冗余调用?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-09-05 21:37:46

您可以只将第三个参数放在let中,以便共享x

代码语言:javascript
复制
f2 a b = let x = expensive a b in \c -> cheap x c

(在这种情况下,f2 a b = let x = expensive a b in cheap x也可以使用。)

你正在寻找的是编译器驱动的partial evaluation,这是一个很难解决的问题……至少它很难正确地实现,以至于它不在GHC中。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12282717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档