答案 0 :(得分:13)
答案 1 :(得分:9)
关于do
符号本身,它可能有助于考虑实际的优点。正如特拉维斯·布朗所指出的那样,我之前曾主张使用带有Monad
和相关类型的“函数应用程序”样式,但也有另一面:有些表达式根本无法使用以直接的功能应用风格写得干净利落。例如,以下内容可以迅速使应用风格笨拙:
将这样的函数编写为单个表达式通常需要多个嵌套的lambdas,或者是一种荒谬的混淆废话,它使无点样式成为坏名称。另一方面,do
块提供语法糖,以便使用嵌入式控制流轻松嵌套中间结果的范围。
通常你可能会提取这样的子表达式并将它们放在where
子句中,但是因为普通值形成了一个monad,其函数应用为(>>=)
- 即Identity
monad - 你可以想象在do
块中编写这样的函数,尽管人们可能会看着你很有趣。
除了作用域/绑定之外,do
块为你做的另一件事就是将子表达式链接在一起的运算符。想象一下“在这个块中使用这个函数组合这些表达式”然后让编译器填入空白的其他情况并不难。
在简单的情况下,表达式都具有相同的类型,将它们放在列表中然后折叠它也很有效 - 使用unwords
和unlines
以这种方式构建字符串。 do
的好处是它将表达式与通用结构和兼容(但不完全相同)类型相结合。
事实上,同样的一般原则也适用于Applicative
论文中的“成语括号”符号:do
块使用换行符来消除monadic构造,成语括号使用并列来消除提升函数应用。 proc
的{{1}}符号也类似,其他概念也可以用这种方式清晰表达,例如:
虽然将这些中的许多变成单个类型或完整的Arrow
实例并不太难,但为一般概念提供统一的,可扩展的语法糖可能会很好。当然有一个共同的线索将所有这些和更多的东西捆绑在一起,但这是一个与语法无关的更大的话题......
答案 2 :(得分:7)
答案 3 :(得分:5)
成语括号构成了一种考虑Applicatives的好方法,但它们并不是唯一可能的语法扩展。
菲利普·考德罗伊(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
然而,词汇范围规则有点令人不安。
答案 4 :(得分:3)
答案 5 :(得分:3)
BlazeHtml正在使用do
- 表示实际上它只是Monoid
(虽然包装为Monad
以便能够使用do
)。< / p>
因此Monoid
s的类似符号在那里很有用。
如果你看一下我的游戏"Defend The King"的代码,那么我也会做很多mconcat
,就像BlazeHtml一样,我会从一个漂亮的语法中受益。
答案 6 :(得分:2)
对monad的推广符合do
符号 - 参数化monad。请参阅sigfpe的Beyond Monads。用法示例:
test1' = do put 1
x <- get
put (show x)
y <- get
return (x,y)
这是一个“状态monad”,它首先存储一个数字,然后是一个字符串。
答案 7 :(得分:1)