在不进行评估的情况下执行操作

时间:2013-09-17 02:23:57

标签: haskell eval

假设我们有这样的函数:

f:Int->Int

根据输入提供修改后的输出。

我的问题是,无论如何我可以写这个函数,所以没有对输入进行评估吗?例如,考虑以下预期的输入和输出:

输入:3 + 2/1 + 90

输出:3 + 2/1 + 90 + 2

[编辑] 我听说过Haskell的懒惰评估,但我刚才意识到这正是我想要的,只要我不调用print,实际上在解析树中没有进行评估。

1 个答案:

答案 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