你可以请求 GHC 的 desugarer 输出,不过这将会对很多其他语法进行反糖处理。
首先,我们将把你的代码放在一个名为 Foo.hs
的模块中:
module Foo where
a = do x <- [3..4]
[1..2]
return (x, 42)
接下来,我们将要求 GHC 编译它,并在解糖阶段后输出结果:
$ ghc -c Foo.hs -ddump-ds
输出可能看起来相当混乱,因为它是Haskell的一种变体,称为Core,用作GHC的中间语言。然而,一旦你熟悉它,它并不太难阅读。在其他一些定义的中间,我们发现了你的定义:
Foo.a :: [(GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)]
LclIdX
[]
Foo.a =
>>=_agg
@ GHC.Integer.Type.Integer
@ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)
(enumFromTo_ag7
(GHC.Integer.smallInteger 3) (GHC.Integer.smallInteger 4))
(\ (x_adf :: GHC.Integer.Type.Integer) ->
>>_agn
@ GHC.Integer.Type.Integer
@ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)
(enumFromTo_ags
(GHC.Integer.smallInteger 1) (GHC.Integer.smallInteger 2))
(return_aki
@ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)
(x_adf, GHC.Integer.smallInteger 42)))
Core 不太好看,但是当你使用 GHC 时能够阅读它会非常有用,因为在后期阶段可以读取转储信息,查看 GHC 如何优化代码。
如果我们删除重命名器添加的 _xyz 后缀,以及类型应用程序 @ Xyz 和对 GHC.Integer.smallInteger 的调用,并使操作符再次成为中缀形式,你就会得到像这样的东西:
Foo.a :: [(GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)]
Foo.a = enumFromTo 3 4 >>= \x -> enumFromTo 1 2 >> return (x, 42)
m >>= (\_ -> k)
等同于m >> k
。 - Matvey Aksenov