如何自动括起任意haskell表达式?

时间:2016-10-30 16:31:20

标签: haskell

我正在学习haskell,在思考我遇到的许多haskell表达式时遇到了很多困难。

当然,我希望通过足够的练习,精神解析haskell将成为第二天性,但与此同时,为了理解我遇到的问题,我想找到一些自动方式将任意"标准的haskell" 1 表达式翻译成一个表达式,其中所有"不明确的" 2 子表达式已被消除介绍必要的括号。

例如,它会翻译表达式

f g h i

...成

((f g) h) i

......,或

a -> b -> c -> d

...成

a -> (b -> (c -> d))

......等等。

最好,这是我可以使用手机访问的工具,因为我在远离正确的计算机时对haskell进行了很多阅读。

1 当然,没有这样的工具可以使用未知固定性和关联性的自定义操作符。通过"标准haskell"我指的是前奏和标准haskell库中定义的东西。

2 我正在使用"模棱两可的"这里作为"在没有优先规则的情况下模棱两可的简写"。例如。 2 + 3 * 5含糊不清除非有一些优先规则可以解决首先执行哪两项操作的问题。

2 个答案:

答案 0 :(得分:10)

如果你真的想去做它的工作,你可以写一个TemplateHaskell函数来为你做这个 - 你基本上只是走AST并随意添加parens。我开始这样做了,但意识到它会变得非常冗长乏味。我认为现在可能更方便你只考虑实际发挥作用时的currying(功能没有完全应用)。

但是,您可以使用一个技巧来解决问题的一个子问题:围绕运营商的问题,这些运营商的固定性和关联性不熟悉。在GHCi中,在使用正确的标志启动之后,只需将您感兴趣的表达式包装在$([| <expression> |])中进行检查。然后,您可以在评估结果之前看到表达式的括号版本。

$ ghci -ddump-splices -XTemplateHaskell
Prelude> $([| 1 + 2 ^ 3 * 4 |])
<interactive>:1:3-21: Splicing expression
    [| 1 + 2 ^ 3 * 4 |] ======> (1 + ((2 ^ 3) * 4))
33
Prelude> $([| 1 <$ pure 4 >>= \x -> const mempty =<< [(+),(*)] <*> [1,2] <* [False] |])
<interactive>:2:3-77: Splicing expression
    [| 1 <$ pure 4
       >>=
         (\ x_a6PT -> const mempty =<< [(+), (*)] <*> [1, 2] <* [False] |]
  ======>
    ((1 <$ (pure 4))
     >>=
       (\ x_a6PT
          -> ((const mempty) =<< (([(+),(*)] <*> [1,2]) <* [False]))))
[]
Prelude>

然而,这绝对不会以您想要的方式修复类型签名或功能应用程序。

答案 1 :(得分:4)

这不完全是你所要求的,但是当我 Haskell时,我发现使用HLint警告我不必要的麻烦'正在阅读

您可能还会发现Bernie Pope's "A tour of the Haskell Prelude"第23页上的图表很有帮助。我在下面附上了一份副本。

page 23 of Bernie Pope's "A tour of the Haskell Prelude"