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

ye9*_*ane 1 haskell eval

假设我们有这样的函数:

f:Int->Int
Run Code Online (Sandbox Code Playgroud)

它为我们提供了基于输入的修改输出.

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

输入:3 + 2/1 + 90

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

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

Dan*_*zer 8

在Haskell中,事情总是很懒惰,所以你总是会有一个相当的计算,3+2/1+90+2但是当你要求印刷版本时,你会对它进行评估.

你可以做这样的事情

f x = x + 2

main = do
  let x = f (error "Kaboom!!")
  print 1
Run Code Online (Sandbox Code Playgroud)

并运行它很好,但试图打印它将迫使评估.

main = do
   let x = f (error "Kaboom!!")
   print x
Run Code Online (Sandbox Code Playgroud)

哪个会出错.这个故事有一些细微之处在于评估事物的时间/时间,但这是它的要点.

在这一点上,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
Run Code Online (Sandbox Code Playgroud)

Daniel Wagner指出,如果你想继续这个想法:简单反思