假设我们有一个这样的函数:
f:Int->Int
这为我们提供了基于输入的修改后的输出。
我的问题是,无论如何我可以编写这个函数,以便不对输入进行评估吗?例如,考虑以下预期的输入和输出:
输入:3+2/1+90
输出:3+2/1+90+2
[编辑] 我听说过 Haskell 的惰性求值,但我只是意识到这正是我想要的,只要我不调用打印,实际上解析树中不会进行任何求值。
在 Haskell 中,事情总是懒惰的,所以你总是会有一个等效的计算,3+2/1+90+2
但是当你要求打印版本时,你会评估它。
你可以做这样的事情
f x = x + 2
main = do
let x = f (error "Kaboom!!")
print 1
运行它就好了,但试图打印它会强制评估。
main = do
let x = f (error "Kaboom!!")
print x
哪个会出错。这个故事在评估多少/何时评估事物方面有一些微妙之处,但这就是它的要点。
在这一点上,Haskell 已经失去了“漂亮打印”计算的所有能力,所有信息都被编译成显式闭包和其他丑陋的东西。如果你想观察计算的建立,有一个有趣的技巧
newtype TraceableNum = Trace { runTrace :: String }
instance Num TraceableNum where
(Trace a) + (Trace b) = Trace $ "(" ++ a ++ " + " ++ b ++ ")"
(Trace a) - (Trace b) = Trace $ "(" ++ a ++ " - " ++ b ++ ")"
(Trace a) * (Trace b) = Trace $ "(" ++ a ++ " * " ++ b ++ ")"
abs (Trace a) = Trace $ "abs(" ++ a ++ ")"
signum (Trace a) = Trace $ "signum(" ++ a ++ ")"
fromInteger = Trace . show
main = print . runTrace $ 1 + 4 * 7
Daniel Wagner 指出如果你想继续这个想法:simple-reflect