我正在探索Haskell以获得乐趣,并了解该语言。我认为以下行为很有趣,我无法找到发生这种情况的原因。
这是一个经常被引用的Haskell代码,它一直计算pi直到被中断,稍微修改以给出一个连续的字符列表而不是一个整数列表:
main :: IO ()
main = do putStrLn pi'
pi' :: [Char]
pi' = concat . map show $ g(1,0,1,1,3,3) where
g(q,r,t,k,n,l) =
if 4*q+r-t<n*t
then n : g(10*q,10*(r-n*t),t,k,div(10*(3*q+r))t-10*n,l)
else g(q*k,(2*q+r)*l,t*l,k+1,div(q*(7*k+2)+r*l)(t*l),l+2)
如果我从prelude运行它,它会开始连接类似pi的数字的字符串:
λ> putStrLn pi'
31415926535897932384626433832795028841971
...等
按预期工作,它会立即开始喷出数字。
现在这是我刚刚写的一段具有相同结构的代码。从数学的角度来看,它完全无用,我只是在弄乱Haskell如何工作。操作更简单,但它的类型相同,子函数也是如此(除了较小的元组)。
main :: IO ()
main = do putStrLn func
func :: [Char]
func = concat . map show $ h(1,2,1) where
h(a,b,c) =
if a <= 1000
then a : h((div a 1)+2*b,b,1)
else h(b,div (b-3) (-1),div a a)
前奏相同类型的结果:
λ> putStrLn func
1591317212529333741454953576165697377818589
...等
按预期工作,虽然比pi功能快得多,但因为计算不太复杂。
如果我编译:{{1}}并运行我的程序:ghc pi.hs
,输出将永远保持空白,直到我发送中断信号。在那一刻,立即显示整个计算的pi字符串。它没有&#34;流&#34;输出到stdout,就像GHCI一样。好的,我知道他们并不总是以同样的方式行事。
但接下来我运行:./pi
,运行我的程序:ghc func.hs
...然后立即开始打印字符列表。
这种差异来自哪里?我认为这可能是因为我的愚蠢无用的小功能(最终)重复,所以编译器可以预测&#34;输出更好?
或者功能的运作方式还有另一个根本区别吗?或者我在做一些完全愚蠢的事情?
由Thomas&amp;提供丹尼尔,我是:
所以重写主函数后:
./func
它被修复了!
答案 0 :(得分:2)
由Thomas&amp;提供丹尼尔在评论中说,原来我是:
所以重写主函数后:
import System.IO
main :: IO ()
main = do hSetBuffering stdout NoBuffering
putStrLn pi'
它被修复了!