Haskell中的诊断输出

Sh4*_*4pe 3 haskell

我学习了命令式语言的编程,主要是C++和C语言,所以函数式方法对我来说是非常新的.

当我以前编写函数/方法时,我通常采用"增量"方法(可能大多数人都这样做):编写一小部分代码,然后检查到目前为止的结果是否符合预期(通常只是将它们打印到stdout with printf或std :: cout),改进算法,增强算法,然后检查到目前为止的结果是否符合预期(通常只需用printf或std :: cout打印到stdout),精炼...我非常很少把整个方法写成一个整体.

这种"增量"方法的关键是具有诊断输出的能力(在上面的例子中是printf或std :: cout).但是在Haskell中(据我现在所理解的),如果我想 - 比如说 - 使用'putStrLn'向stdout写一些东西,我必须改变我的函数的签名,因为'putStrLn'只返回一个IO Monad包含我想要打印的信息,但是在调用'putStrLn'时不打印它,对吗?因此,每次我想使用'putStrLn'进行诊断输出时,我必须更改当前函数的签名以及我所有其他函数调用它的方式等...

那么有一种廉价而简单的方法可以将函数的"局部变量"的值打印到标准输出中吗?

或者仅仅是因为我要求这个标志我不理解Haskell编程的基本部分?

Phi*_* JF 13

没有好办法做你想做的事.你可以接近Debug.Trace但我不建议在学习时因为Haskell的非标准评估顺序.Haskell不能像C和C++这样的语言顺序设置"变量"的值.因为它是惰性的,所以Haskell表达式按照依赖于使用的顺序进行评估,因此增量值的东西并不真正起作用.

Haskell是一种面向表达的语言.使用它对您有利:

  1. 写短函数.通过这种方式更容易看出每个函数的作用.大多数函数应该是每个方程一行,真正的"一个衬里"应该是常见的.
  2. 使用REPL.你应该不断在GHCi中试验你的代码
  3. 使用类型系统.Haskell的类型系统比大多数命令式语言中的类型系统更有用.类型以机器检查方式记录文档意图.如果不了解类型,就不能指望理解代码.编写代码时,一旦获得了正确的类型,就可以完成大部分工作.

结合以上建议.您可以在GHCi中获取表达式的类型:t.


And*_*ewC 8

这很奇怪,因为我发现在您习惯使用的语言中没有Read Eval Print Loop(REPL),我一直很沮丧,因为我一直在测试我的代码需要做多少工作.REPL是我增量代码开发的基础; 您可以使用它来测试代码,无需添加一堆打印语句.

  • 让GHCi与您的编辑同时打开.
  • 编写较小的单用途函数.这看起来很古怪,但函数应用程序是Haskell中的基本工作单元,并且没有您在命令式语言中获得的那种开销.
  • 每次编写函数时,:r都要在GHCi中进行测试并使用各种输入进行测试.
  • Haskell非常密集,因此在屏幕上制作单独的函数要比你习惯的要短得多.

偶尔你会陷入冗长的monadic计算或其他东西.GHCi允许您设置断点 - 优先使用这些断点来向代码添加打印语句,因为您可以在不编辑代码的情况下搞砸并进行更多调查,最重要的是,您不需要在类型签名上添加显示约束.

完成后,您可以手动无意中内联辅助函数并编译ghc -O2.

(根据Debug.Trace我的经验,使用手动添加的打印语句或模块是完全痛苦的.)

摘要:尽可能避免在测试时编辑代码.使用GHCi很多.