使用 `seq` 并在 haskell 中打印

Use `seq` and print in haskell

我知道这有点棘手,但我想知道为什么它不起作用!

module Main where

sillyDebug :: Int -> Int -> Int
sillyDebug x y =
    (print x) `seq` (x + y)

main :: IO ()
main = do
    print (sillyDebug 1 2)

而其理想与

相同
sillyDebug = (trace (show x) False) `seq` (x + y)

是否与haskell中的惰性求值或副作用有关? https://hackhands.com/lazy-evaluation-works-haskell/

仅仅评估一些 IO 行动根本没有任何作用。你可以认为 IO 有点像所有可能 side-effectful 事情的真正大和类型 Haskell 可以 做,即使它不是'实际上根本没有那样实现。像这样:

data IO a where
  PutStrLn :: String -> IO ()
  ReadFile :: FilePath -> IO String
  ExitWith :: ExitCode -> IO a
  ...

此理论可视化中的 IO 构造函数之一将是 Sequence 构造函数,其类型签名如下:

  Sequence :: IO a -> (a -> IO b) -> IO b

此构造函数用于为 IO 类型实现 >>=

GHC 内部有一个名为 magicallyExecuteIO 的神奇函数,类型为 IO a -> a,它协调每个动作实际执行其对应的 side-effect。 (顺便说一句,这个函数有时也读作 unsafePerformIO。)GHC 隐式调用 magicallyExecuteIO 程序的 main 函数的结果,以及用 GHCi 编写的表达式。

然而,在不使用 magicallyExecuteIO 的情况下,评估 IO 构造函数之一,如 PutStrLn 不会做任何事情。在此实现中,它将像任何其他数据构造函数一样工作:

ghci> Just (PutStrLn "hello!")
Just (PutStrLn "hello!") :: Maybe (IO ())

(我用 Just 包裹它以防止 GHCi 运行 执行 IO 操作。)

当然,GHC 的实际 IO 类型并不是这样实现的,但这实际上只是一个实现细节。评估 IO a 值不会导致 side-effect 发生,而评估 Maybe a 值不会。只有 magicallyExecuteIO 可以做到。