Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell:换行函数_Haskell - Fatal编程技术网

Haskell:换行函数

Haskell:换行函数,haskell,Haskell,晚上好 哈斯凯尔从事的一个项目包括构建一个简单的语言解释器,他之所以被选中是因为他的功能性 我的问题如下。我有很多函数(这些函数中的模式匹配)可以实际计算一些东西。我想在屏幕上打印我所有函数的每个函数应用程序的一个参数(类型为Context) 例如: booleanExpression (And b1 b2) ctx = b1' and b2' booleanExpression (Or b1 b2) ctx = b1' or b2' ... arithmeticExpression (Mu

晚上好

哈斯凯尔从事的一个项目包括构建一个简单的语言解释器,他之所以被选中是因为他的功能性

我的问题如下。我有很多函数(这些函数中的模式匹配)可以实际计算一些东西。我想在屏幕上打印我所有函数的每个函数应用程序的一个参数(类型为Context)

例如:

booleanExpression (And b1 b2) ctx = b1' and b2' 
booleanExpression (Or b1 b2) ctx = b1' or b2'
...

arithmeticExpression (Multiply a1 a2) ctx = a1' * a2'
....
对于这些函数,我希望在每次调用函数时打印ctx。 有没有一个简单的方法可以做到这一点?或者我必须用类似的东西封装每个函数

arithmeticExpression (Multiply a1 a2) ctx = printAndExec ctx $ a1' * a2'

谢谢。

在Haskell中,在每次评估之间打印一些东西的想法通常被认为是不雅的。它以一种更难对代码进行推理的方式将纯粹而有效的计算交织在一起。它也不像严格的语言所期望的那样具有确定性:惰性意味着纯代码中的print语句可能会被多次计算,或者根本不会得到任何警告

解决这个问题的自然方法是在一个排序单子中执行事情。Writer是一个相当纯粹的Monad,它允许您将
ctx
打印到一个缓冲区,然后在稍后的阶段实际写出该缓冲区。懒惰实际上会使缓冲和书写结合在一起,从而使其看起来天衣无缝

另一个选项是将计算提升到
IO
monad中,并具有完整的排序和访问所有效果的权限。看起来你的计算需要通过某种AST进行递归——你可以从每次递归调用中返回一元操作,比如
IO Int
,而不是它们的纯表亲
Int
,这样你就可以在遍历树时构建一个不纯的计算


如果您只需要打印CTX用于调试目的,最后要考虑的是<代码>调试.Trace< /Cult>模块,它包括纯代码中的纯打印方法。但是,在生产代码中包含这些函数是一个错误的决定。

通常,在Haskell中,在每次求值之间打印某些内容的想法被认为是不雅观的。它以一种更难对代码进行推理的方式将纯粹而有效的计算交织在一起。它也不像严格的语言所期望的那样具有确定性:惰性意味着纯代码中的print语句可能会被多次计算,或者根本不会得到任何警告

解决这个问题的自然方法是在一个排序单子中执行事情。Writer是一个相当纯粹的Monad,它允许您将
ctx
打印到一个缓冲区,然后在稍后的阶段实际写出该缓冲区。懒惰实际上会使缓冲和书写结合在一起,从而使其看起来天衣无缝

另一个选项是将计算提升到
IO
monad中,并具有完整的排序和访问所有效果的权限。看起来你的计算需要通过某种AST进行递归——你可以从每次递归调用中返回一元操作,比如
IO Int
,而不是它们的纯表亲
Int
,这样你就可以在遍历树时构建一个不纯的计算


如果您只需要打印CTX用于调试目的,最后要考虑的是<代码>调试.Trace< /Cult>模块,它包括纯代码中的纯打印方法。但是,在生产代码中包含这些函数是一个错误的决定。

您想要做的可以描述为面向方面的编程,或者(进一步推广)元编程。Haskell确实提供了一种元编程工具,称为模板Haskell,所以这将是一种实现方法

但是,如果您有多个相同类型的函数,则可能有一种更简单的方法。然后你可以把它们放在一个列表中

map (\f y ctx -> printAndExec ctx $ f y ctx) list

但是,您必须将列表中的元素分配给函数名,这并不是很优雅。

您想要做的可以描述为面向方面的编程,或者(进一步推广)元编程。Haskell确实提供了一种元编程工具,称为模板Haskell,所以这将是一种实现方法

但是,如果您有多个相同类型的函数,则可能有一种更简单的方法。然后你可以把它们放在一个列表中

map (\f y ctx -> printAndExec ctx $ f y ctx) list
但是,您必须将列表中的元素分配给函数名,这并不是很优雅