为什么每秒两次读取不断变化的文件给出相同的值?

Dog*_*Dog 4 haskell lazy-evaluation

我刚在Haskell写了这个内容,看看我每秒使用多少带宽:

>>> import Control.Monad (forever)
>>> import Control.Concurrent (threadDelay) -- microseconds; 10^6?s = 1s
>>> let f = "/sys/class/net/wlan0/statistics/rx_bytes" in forever $ readFile f >>= \a -> threadDelay (10^6) >> readFile f >>= \b -> print (read b - read a)
0
0
0
0
0
0
0
0
0
Run Code Online (Sandbox Code Playgroud)

但它总是说0.我在Bash中并行运行了一行等效的代码,这表明该文件确实在此期间发生了变化:

$ f=/sys/class/net/wlan0/statistics/rx_bytes; while true; do a=`cat $f`; sleep 1; echo $((`cat $f`-a)); done
98
98
2132
3178
230
306
98
98
729
Run Code Online (Sandbox Code Playgroud)

为什么Haskell看不到变化?

lef*_*out 11

readFile是懒惰的,即它实际上不会访问文件中的数据,直到你评估绑定到它的变量:在你的情况下,read a.此时线程延迟已经过去,您评估文件的状态与b!相同!

这样做:

forever $ do
   a <- fmap read $ readFile f
   a `seq` threadDelay (10^6)
   b <- fmap read $ readFile f
   print $ b - a
Run Code Online (Sandbox Code Playgroud)