假设我们有这样的函数:
f:Int->Int
根据输入提供修改后的输出。
我的问题是,无论如何我可以写这个函数,所以没有对输入进行评估吗?例如,考虑以下预期的输入和输出:
输入:3 + 2/1 + 90
输出:3 + 2/1 + 90 + 2
[编辑] 我听说过Haskell的懒惰评估,但我刚才意识到这正是我想要的,只要我不调用print,实际上在解析树中没有进行评估。
答案 0 :(得分:8)
在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