【问题标题】:How to automatically parenthesize arbitrary haskell expressions?如何自动给任意haskell表达式加上括号?
【发布时间】:2016-10-30 16:31:20
【问题描述】:

我正在学习 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”是指prelude和标准haskell库中定义的东西。

2我在这里使用“模糊”作为“在没有优先规则的情况下模糊”的简写。例如。 2 + 3 * 5 是模棱两可的除非有一些优先规则可以解决两个操作中的哪一个将首先执行的问题。

【问题讨论】:

  • 我在你的手机上想不出任何东西,但是你可以在 GHCi 中做一些非常简单的事情
  • 好吧,haskell-src-exts 可以很容易地获得一个完全明确的解析树并将其打印出来。但它不是真正可读的。安装后尝试使用 ghci 中的 (fmap . fmap . fmap) (const ()) (parseFile "foo.hs")
  • @Alec:我到底能在 ghci 中做什么? (关于电话:这只是一种偏好,而且是一种温和的偏好,以防万一这件事有选择;如果没有,我很乐意接受 ghci。)
  • This brand new tool 似乎与您在术语级别中描述的完全一样。
  • 感谢您的提醒!对于haskell noob(比如我)来说,这看起来像是天赐之物。

标签: haskell


【解决方案1】:

如果你真的想去做它,你可以编写一个TemplateHaskell 函数来为你做这件事——你基本上只是遍历 AST 并随意添加括号。我开始这样做,但意识到它会很快变得很长而且很乏味。我认为暂时只在实际发挥作用时才考虑柯里化可能更方便(使用未完全应用的功能)。


但是,您可以使用一个技巧来解决问题的子情况:围绕您不熟悉的固定性和关联性的运算符进行括号。在 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>

但是,这绝对不会以您想要的方式修复类型签名或函数应用程序。

【讨论】:

    【解决方案2】:

    这并不完全符合您的要求,但我发现在我编写时使用 HLint 警告我不必要的括号 Haskell 对我有很大帮助阅读

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

    【讨论】:

      猜你喜欢
      • 2018-04-07
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-28
      • 1970-01-01
      相关资源
      最近更新 更多