Ответ 1
Вы можете запросить вывод GGC desugarer, но это также приведет к значительному снижению синтаксиса.
Сначала мы поместим ваш код в модуль Foo.hs
:
module Foo where
a = do x <- [3..4]
[1..2]
return (x, 42)
Далее, мы попросим GHC скомпилировать его и вывести результат после этапа desugaring:
$ 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)))
Ядро не слишком красивое, но возможность его чтения очень полезна при работе с GHC, поскольку вы можете прочитать дамп после более поздних этапов, чтобы узнать, как GHC оптимизирует ваш код.
Если мы удалим суффиксы _xyz
, добавленные renamer, а также приложения типа @ Xyz
и вызовы на GHC.Integer.smallInteger
, и снова запустим операторы infix, вы получите что-то вроде этого:
Foo.a :: [(GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)]
Foo.a = enumFromTo 3 4 >>= \x -> enumFromTo 1 2 >> return (x, 42)