我知道这有点棘手,但我想知道为什么它不起作用!
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/
答案 0 :(得分:4)
仅仅评估一些IO
行动根本不做任何事情。您可以认为IO
类似于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
,它协调每个动作以实际执行其相应的副作用。 (顺便提一下,这个函数有时也发音为unsafePerformIO
。)GHC隐式调用程序magicallyExecuteIO
函数结果的main
,以及用GHCi编写的表达式。
但是,如果不使用magicallyExecuteIO
,则评估其中一个IO
构造函数(如PutStrLn
)不会执行任何操作。在这个实现中,它将像任何其他数据构造函数一样工作:
ghci> Just (PutStrLn "hello!")
Just (PutStrLn "hello!") :: Maybe (IO ())
(我已将其与Just
包装在一起,以防止GHCi执行IO
操作。)
当然,GHC的实际IO
类型没有以这种方式实现,但这实际上只是一个实现细节。评估IO a
值不会导致副作用发生,只会评估Maybe a
值。只有magicallyExecuteIO
可以做到这一点。