Haskell 2010年报告说
do表达式为monadic编程提供了更常规的语法。它允许一个表达式,例如
putStr "x: " >> getLine >>= \l -> return (words l)用更传统的方式写成:
do putStr "x: " l <- getLine return (words l)
汤普森说,Haskell函数编程技巧说
我们将继续使用do表示法,但要记住,它本质上 归结为一个函数(>> =)的存在,该函数负责对I / O程序进行排序并将其结果绑定以供将来使用。
以上是否意味着必须在monad的上下文中使用符号?
如果是,为什么以下函子使用do表示法?
instance Functor IO where -- fmap :: (a -> b) -> IO a -> IO b fmap g mx = do {x <- mx; return (g x)}
AJFarmar.. 5
是。正如文章所引用的那样,- do
符号只是 monad操作的语法糖 。
这些是去糖符号的规则do
:
do {foobar; ...} = foobar >> do {...}
(又名foobar >>= \_ -> do {...}
)
do {a <- foobar; ...} = foobar >>= \a -> do {...}
do {foobar} = foobar
必要的是,这意味着- do
注释完全适用于monad,除非在规则3所描述的琐碎情况下。
因此,例如,如文章所述,do {putStr "x: "; l <- getLine; return (words l)}
它等于putStr "x: " >> (getLine >>= \l -> return (words l))
,您可以通过除糖规则进行确认。
在Functor IO
上面引用的定义中,Monad IO
实例已经定义,因此我们也使用它来定义Functor
实例。
这也可能是要注意,所有的单子都是必然仿函数(见有用的定义Monad
类型类),所以当一个人说do
-notation作品的单子,这也必然适用于函子为好。我怀疑这可能是一个混淆点。
值得注意的是,在某些受限情况下,可以仅使用Applicative
操作而不是更常规的Monad
操作。例如,文章提供的示例可以写为putStr "x: " *> (pure words <*> getLine)
。有一个实验语言扩展名为ApplicativeDo
GHC,它使GHC能够识别这些情况并将某些do
符号的情况推广到所有应用程序,而不仅是所有monad。
是。正如文章所引用的那样,- do
符号只是 monad操作的语法糖 。
这些是去糖符号的规则do
:
do {foobar; ...} = foobar >> do {...}
(又名foobar >>= \_ -> do {...}
)
do {a <- foobar; ...} = foobar >>= \a -> do {...}
do {foobar} = foobar
必要的是,这意味着- do
注释完全适用于monad,除非在规则3所描述的琐碎情况下。
因此,例如,如文章所述,do {putStr "x: "; l <- getLine; return (words l)}
它等于putStr "x: " >> (getLine >>= \l -> return (words l))
,您可以通过除糖规则进行确认。
在Functor IO
上面引用的定义中,Monad IO
实例已经定义,因此我们也使用它来定义Functor
实例。
这也可能是要注意,所有的单子都是必然仿函数(见有用的定义Monad
类型类),所以当一个人说do
-notation作品的单子,这也必然适用于函子为好。我怀疑这可能是一个混淆点。
值得注意的是,在某些受限情况下,可以仅使用Applicative
操作而不是更常规的Monad
操作。例如,文章提供的示例可以写为putStr "x: " *> (pure words <*> getLine)
。有一个实验语言扩展名为ApplicativeDo
GHC,它使GHC能够识别这些情况并将某些do
符号的情况推广到所有应用程序,而不仅是所有monad。