好吧也许这里有一个愚蠢的问题,但我目前正在通过在projecteuler.net上完成问题来学习haskell
我遇到了一个有趣的观察,并希望有人可以解释为什么事情就像他们一样。
供参考,我正在实施Problem #29 这就是我的意思
nub $ [ a^^b | a <- [2..100], b <- [2..100] ]
我发现使用^^
运算符的速度比**
快,这比上面列出的输入快^
。
我的问题很简单,为什么?这些运算符中的每一个都适用于不同的类型。我的猜测是有一些类型的转换正在发生,但我希望^
更快的操作,当它看起来实际上是对话时。
谢谢!
答案 0 :(得分:4)
**
和^^
正在使用Double
,但^
正在使用Integer
。你真的无法将浮点运算与大整数函数进行比较。看看implementation of ^
。
在您的代码中,以下情况属实:
**
在硬件中实现。^
在尾递归循环中使用大Integer
。^^
是相同的,但Double
除外。所以你对他们相对表现的观察是有道理的。
答案 1 :(得分:4)
所有时间都用在nub
上。使用^^
和**
,您在nub
上正在[Double]
。 ^
nub
[Integer]
上{{1}},比较大整数比比较双倍慢。
答案 2 :(得分:1)
我在解决Project Euler问题时发现的事情是类型可以在运行时性能上产生巨大差异。例如:
foo :: Integral a => a -> a
foo' :: Integer -> Integer
foo'' :: Int -> Int
所有表现都非常不同。想象一下,当我发现简单地让编译器推断出foo
的最通用类型而不是自己指定它时,我感到惊讶的是导致性能不佳。
性能(显然)高度依赖于您的环境:您是在运行编译还是解释?优化还是未优化?关键在于,在某些情况下,你可能有未装箱的原始Int#
,而不是盒装的,堆分配的值...不幸的是我自己还是一个n00b,我不知道什么时候你会得到一个与另一个:(
所以,这可能是一个愚蠢的答案,但是如果您使用GHC并且熟悉C编程,请尝试使用-keep-hc-files
标志来比较使用{{1时生成的中间C代码} {} ^
与^^
。