gpt4 book ai didi

list - Haskell:编译函数与解释函数之间的奇怪差异,这些函数打印连接的无限列表

转载 作者:行者123 更新时间:2023-12-04 21:14:03 25 4
gpt4 key购买 nike

我只是为了好玩而探索 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 函数快得多,因为计算不那么复杂。

现在让我困惑的部分:

如果我编译: ghc pi.hs ,然后运行我的程序: ./pi ,输出永远保持空白,直到我发送中断信号。在那一刻,整个计算出的 pi 字符串立即显示出来。它不会像 GHCI 那样将输出“流”到标准输出中。好吧,我知道他们并不总是以同样的方式行事。

但接下来我运行: ghc func.hs ,然后运行我的程序: ./func ...它立即开始打印字符列表。

这种差异从何而来?我认为这可能是因为我愚蠢的无用小函数(最终)重复了,所以编译器可以更好地“预测”输出?

或者这些功能的工作方式之间是否存在另一个根本区别?还是我在做一些非常愚蠢的事情?

解决方案/答案

由下面的 Thomas & Daniel 提供,我是:
  • 不耐烦。大块最终会出现在 pi 函数中,在我简单的旧编码机上它只是有点慢。
  • 不以任何方式处理缓冲。

  • 所以在重写main函数之后:
    import System.IO

    main :: IO ()
    main = do hSetBuffering stdout NoBuffering
    putStrLn pi'

    它是固定的!

    最佳答案

    由 Thomas & Daniel 在评论中提供,结果我是:

  • 不耐烦。大块最终会出现在 pi 函数中,在我简单的旧编码机上它只是有点慢。
  • 不以任何方式处理缓冲。

  • 所以在重写main函数之后:
    import System.IO

    main :: IO ()
    main = do hSetBuffering stdout NoBuffering
    putStrLn pi'

    它是固定的!

    关于list - Haskell:编译函数与解释函数之间的奇怪差异,这些函数打印连接的无限列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28639613/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com