【发布时间】:2010-07-26 15:17:35
【问题描述】:
我们都喜欢do,我很好奇这种替代语法在理论上是否在 monad 世界之外有用。如果是这样,它将简化哪些其他类型的计算?例如,为 Applicative 提供等效的东西是否有意义?
【问题讨论】:
我们都喜欢do,我很好奇这种替代语法在理论上是否在 monad 世界之外有用。如果是这样,它将简化哪些其他类型的计算?例如,为 Applicative 提供等效的东西是否有意义?
【问题讨论】:
我的感觉是many Haskell programmers don't love do,当您不需要Monad 的全部功能时,支持使用Applicative 的常见论据之一是组合子<$>、<*>等允许非常清晰简洁的编码风格。
即使对于一元代码,许多人更喜欢显式使用=<< 而不是do 表示法。 camccann 的 answer to your previous question about <*> 为这种偏好提供了一个绝妙的论据。
我倾向于使用do 编写我的初稿,然后在我修改时用组合器替换。这只是我自己(内)的经验和品味的问题:对我来说,以一种更命令式的方式(使用do 更方便)通常最容易画出草图,但我认为非do 代码是通常更漂亮。
另一方面,对于箭头,我无法想象不使用proc 和command do。元组很快就变得如此丑陋。
【讨论】:
考虑到do 符号本身,它实际上有什么好处可能会有所帮助。正如 Travis Brown 所指出的,我之前提倡使用带有 Monads 和相关类型的“函数应用程序”样式,但也有另一面:有些表达式根本无法编写干净利落的直接函数应用风格。例如,以下内容会很快使 applicative 样式变得笨拙:
将这样的函数编写为单个表达式通常需要多个嵌套的 lambda,或者是那种荒谬的混淆废话,使无点样式名声不好。另一方面,do 块提供语法糖,以便通过嵌入式控制流轻松嵌套中间结果范围。
通常你可能会提取这样的子表达式并将它们放在where 子句或其他东西中,但由于普通值形成一个函数应用程序为(>>=) 的单子——即Identity 单子——你可以想象而是在 do 块中编写这样的函数,尽管人们可能会觉得你很有趣。
除了范围/绑定的东西,do 块为您做的另一件事是省略将子表达式链接在一起的运算符。不难想象在其他情况下,如果有一个“在这个块中使用这个函数组合这些表达式”的符号会很好,然后让编译器填补空白。
在简单的情况下,所有表达式都具有相同的类型,将它们放在一个列表中然后折叠它可以很好地工作——例如,使用unwords 和unlines 以这种方式构建字符串。 do 的好处是它结合了具有通用结构和兼容(但不完全相同)类型的表达式。
事实上,Applicative 论文中的“惯用括号”表示法也有同样的一般原则:do 块使用换行符来省略一元构造,惯用括号使用并置来省略提升的函数应用程序。 Arrow 的 proc 符号也类似,其他概念也可以用这种方式清晰地表达,例如:
虽然将其中的许多变成单一类型或完整的Monad 实例并不难,但为一般概念提供统一的、可扩展的语法糖位可能会很好。肯定有一个共同的线索将所有这些以及更多内容联系在一起,但这是一个与语法无关的更大主题......
【讨论】:
do 符号基本上是一种表示“根据需要转换为 lambda 并
在两行之间分配>>=”。
当很明显使用什么运算符来汇总所有内容时,最好省略并 利用“换行符”运算符。
可编程换行将是处理材料列表、应用链等的好方法。要制作列表,您还需要一个“可编程凹痕”。真的,你可以拿三个 有意义的位并使它们都可重载:
do 的开头。dos 之间。do 结束。那么你可能不应该再叫它do了。也许它应该只是一个括号。
【讨论】:
成语方括号是考虑应用程序的一种很好的方式,但它们并不是唯一可能的此类语法扩展。
Philippa Cowderoy 不久前向 haskell-cafe 发布了一个 "Applicative do" 表示法的提案,并观察到任何看起来有点像的函数:
foo = do
x <- bar
y <- baz
quux y 1234 x
<- 绑定的变量只出现在最后一行可以用 Applicative 实现——我实际上在方案中为此实现了一个基于语法规则的宏,我称之为“ado”。
这在应用效果的顺序与“自然顺序”不同的情况下很有用,并且假设 Haskell 中存在 'ado' 只会使以下内容脱糖:
foo = (\x y -> quux y 1234 x) <*> bar <*> baz
但是,词法作用域规则有点令人不安。
【讨论】:
Applicative 有(更有限,更紧凑)成语括号,请参阅Applicative Programming with Effects,第 4 页。我相信,Conor McBride 的 Strathclyde Haskell 环境已经实现了这些。
我不知道如何概括这些特殊的语法,但也许我没有给予足够的思考。
【讨论】:
BlazeHtml 使用的是do-notation,而实际上它只是一个Monoid(尽管包装为Monad 以便能够使用do)。
因此,Monoids 的类似符号在那里会很有用。
如果你看一下我的游戏代码"Defend The King",那么我也做了很多mconcating,就像 BlazeHtml 一样,我会从漂亮的语法中受益。
【讨论】:
有一个符合 do 表示法的单子泛化 - 参数化单子。请参阅 sigfpe 的Beyond Monads。示例用法:
test1' = do put 1
x <- get
put (show x)
y <- get
return (x,y)
这是一个“状态单子”,首先存储一个数字,然后是一个字符串。
【讨论】:
GHC 中有一个预处理器可以为 Arrows 执行此操作:http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/arrow-notation.html
【讨论】: