为 Monad 脱糖 do-notation [英] Desugaring do-notation for Monads

查看:18
本文介绍了为 Monad 脱糖 do-notation的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在学习 Haskell 时,我意识到 do 符号只是语法糖:

As I'm learning Haskell I'm realizing that do notation is just syntatic sugar:

a = do x <- [3..4]
       [1..2]
       return (x, 42)

翻译成

a = [3..4] >>= (x -> [1..2] >>= (\_ -> return (x, 42)))

我意识到我可能会使用 do-notation,但我想了解翻译中发生了什么.所以纯粹出于教学原因,ghc/ghci 有没有办法为我用 do-notation 编写的相当复杂的 monad 提供相应的绑定语句?

I realize that I'll probably use do-notation but I'd like to understand whats going on in translation. So purely for pedagogical reasons, is there a way for ghc/ghci to give me the corresponding bind statements for a fairly complex monad written in do-notation?

编辑.事实证明#haskell 上的 lambdabot 可以做到这一点:

Edit. It turns out lambdabot on #haskell can do this:

<Guest61347> @undo do x <- [3..4] ; [1..2] ; return (x, 42)
<lambdabot> [3 .. 4] >>=  x -> [1 .. 2] >> return (x, 42)

这是撤消插件的源代码.

推荐答案

您可以要求 GHC 的 desugarer 的输出,但这也会对许多其他语法进行 desugar.

You can ask for the output of GHC's desugarer, however this will also desugar a lot of other syntax.

首先,我们会将您的代码放入模块 Foo.hs 中:

First, we'll put your code in a module Foo.hs:

module Foo where

a = do x <- [3..4]
       [1..2]
       return (x, 42)

接下来,我们将要求 GHC 编译它并在脱糖阶段后输出结果:

Next, we'll ask GHC to compile it and output the result after the desugaring phase:

$ ghc -c Foo.hs -ddump-ds

输出可能看起来相当混乱,因为它是称为 Core 的 Haskell 变体,用作 GHC 的中间语言.但是,一旦习惯了,阅读起来并不太难.在其他一些定义的中间,我们找到了您的定义:

The output may look rather messy, because it is a variant of Haskell called Core that is used as GHC's intermediate language. However, it's not too hard to read once you get used to it. In the middle of some other definitions we find yours:

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 如何优化您的代码.

Core isn't too pretty, but being able to read it is very useful when working with GHC, as you can read the dump after later stages to see how GHC is optimizing your code.

如果我们删除重命名器添加的 _xyz 后缀,以及类型应用程序 @ Xyz 和对 GHC.Integer.smallInteger,并再次使运算符中缀,你会得到这样的东西:

If we remove the _xyz suffixes added by the renamer, as well as the type applications @ Xyz and the calls to GHC.Integer.smallInteger, and make the operators infix again, you're left with something like this:

Foo.a :: [(GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)]
Foo.a = enumFromTo 3 4 >>= x -> enumFromTo 1 2 >> return (x, 42)

这篇关于为 Monad 脱糖 do-notation的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆