当前位置: 首页 > 知识库问答 >
问题:

有没有办法让这个Haskell程序更快?

易弘亮
2023-03-14
-- Lambda Calculus ADT
data Term = Fun (Term -> Term) | Num !Double
instance Show Term where
    show (Num x) = "(Num "++(if fromIntegral (floor x) == x then show (floor x) else show x)++")"
    show (Fun _) = "(<function>)"

-- Lambda Calculus term application
(#) :: Term -> Term -> Term
(Fun f) # x = f x
infixl 0 # 

-- We have floats as primitives for performance
float_toChurch :: Term
float_toChurch = Fun (\ (Num n) -> Fun (\f -> Fun (\x -> 
    if n <= 0 
        then x 
        else (f # (float_toChurch # (Num (n - 1)) # f # x)))))

float_add :: Term
float_add = Fun (\ (Num x) -> Fun (\ (Num y) -> Num (x + y)))

-- Function compiled from the Lambda Calculus.
-- It sums all nats from 0 til a number.
sum_til :: Term
sum_til = (Fun(\v0->((((((float_toChurch # v0) # (Fun(\v1->(Fun(\v2->(Fun(\v3->(Fun(\v4->((v3 # v2) # (((v1 # ((float_add # v2) # (Num 1))) # v3) # v4))))))))))) # (Fun(\v1->(Fun(\v2->(Fun(\v3->v3))))))) # (Num 0)) # (Fun(\v1->(Fun(\v2->((float_add # v2) # v1)))))) # (Num 0))))

-- Testing it
main = do
    let n = 512*512*8
    print $ (sum_til # (Num n))

由于没有快速的lambda计算器,我使用上面的策略将非类型化lambda演算的术语编译为Haskell,以便快速计算它们。我对它的性能印象深刻:该程序创建了一个从02097152的数字列表,并在我的计算机上在不到一秒钟的时间内将它们相加。这比我预期的要快得多--只比Haskell直接等价物慢4倍--并且足以对我的目标有用。但是,请注意,为了满足类型系统的需要,我必须将函数和术语包装在fun/num构造函数下面。那个拳击很可能不理想。所以,我的问题是:是否有可能运行同样的λ演算程序,甚至更快地得到同样的结果?也就是说,有什么方法可以移除拳击?(另外,它不需要使用Haskell。)

共有1个答案

穆乐逸
2023-03-14
newtype Term = Term (Term -> Term)
 类似资料:
  • 更新: 谢谢所有的帮助。我将总结一下答案。 从@Jayde开始,他的回答成功地将结果减少到0.09秒,并且与限制中的数字成线性关系。 选择*from(选择table1.id作为table1\u id,从table1中选择table1.id 在@Rick James中,他提到这可能是表2的问题。因为我的表2只有几列,所以我可以省略它,自己进行连接,即使是在客户端! 所以我去掉了表2,它只有0.02s

  • 所以我正在做一个需要xml模式的小项目,我对这个模式很不熟悉。 我希望能够设置模式以在两组属性之间进行选择,根据我的研究,这在XSD 1.0中是不可能的,但显然是XSD 1.1的一个特性。 目前我正在使用VisualStudio来完成我的工作,它似乎被困在XSD1.0模式中,这是有意义的,因为XSD1.1显然是一个最新的开发。 我的问题是,是否有一个插件/扩展可以让我在Visual Studio中

  • 我制作一个浏览器只是为了练习我的Java技能,有没有办法让我的地址栏(JTextField)比swing的默认值更大,也更弯曲。这是我的密码。 我想制作一个真正可用的浏览器,就像我想让html及其CSS页面显示一样,我还需要学习什么才能使其工作。

  • 我正在为一个系统建模,该系统有一个创建资源的操作和其他消耗该资源的操作。然而,一个给定的资源只能被消耗一次——有没有一种方法可以保证在编译时这样做? 具体来说,假设第一个操作烘焙蛋糕,还有另外两个操作,一个用于“选择吃”蛋糕,另一个用于“选择吃蛋糕”,我只能做其中一个。 通过在我们使用蛋糕后在蛋糕上设置一个标志,很容易在运行时强制执行不保留已经吃过的蛋糕(反之亦然)的限制。但是有没有办法在编译时强

  • 问题内容: 有没有办法使用泛型说“此方法返回”? 当然,我想在子类中重写此方法,因此声明应与一起使用。 这是一个例子: 根本不起作用:我收到“类型不匹配:无法从Base转换为T”。如果我强制使用强制转换,则覆盖将失败。 问题答案: 不,无法表达这一点。只需声明该方法即可返回类的类型。Java具有协变返回类型,因此无论如何您都可以重写方法以返回更特定的类型。 如果您想为此添加一些标记,则可以随时引入

  • 问题内容: 我正在尝试使用Swift(不是Xcode项目)编写脚本。需要明确的是,我文件的第一行是 我只是从命令行调用它。 但是,我无法弄清楚该脚本如何使用另一个.swift文件中的代码。它不会从同一目录中拾取它,而且我看不到任何方法。 支持吗? 问题答案: 有更好的方法! 如果您要从中导入文件,将像: