[英]Is this syntax as expressive as the do-notation?
該do
表示法允許我們表達單子代碼沒有壓倒嵌套,使
main = getLine >>= \ a ->
getLine >>= \ b ->
putStrLn (a ++ b)
可以表達為
main = do
a <- getLine
b <- getLine
putStrLn (a ++ b)
但是假設語法允許... #expression ...
代表do { x <- expression; return (... x ...) }
do { x <- expression; return (... x ...) }
。 例如, foo = fa #(b 1) c
將被解雇為: foo = do { x <- b 1; return (faxc) }
foo = do { x <- b 1; return (faxc) }
。 上面的代碼可以表示為:
main = let a = #getLine in
let b = #getLine in
putStrLn (a ++ b)
哪個會被貶低為:
main = do
x <- getLine
let a = x in
return (do
x' <- getLine
let b = x' in
return (putStrLn (a ++ b)))
這是等價的。 這種語法對我很有吸引力,因為它似乎提供了與do-notation相同的功能,同時還允許一些較短的表達式,例如:
main = putStrLn (#(getLine) ++ #(getLine))
所以,我想知道這個提議的語法是否有任何缺陷,或者它是否確實完整且等同於do-notation。
putStrLn
已經是String -> IO ()
,所以你的desugaring ... return (... return (putStrLn (a ++ b)))
最終有類型IO (IO (IO ()))
,這可能不是你想要什么:運行這個程序不會打印任何東西!
說到更普遍,你的符號不能表達任何 [見Derek Elkins的評論。] do
-阻塞不中結束return
。
我不相信你的符號可以表達join
,可與表達do
沒有任何附加功能:
join :: Monad m => m (m a) -> m a
join mx = do { x <- mx; x }
但是,你可以表達受限於Monad
fmap
:
fmap' :: Monad m => (a -> b) -> m a -> m b
fmap' f mx = f #mx
和>>=
(因此其他一切)可以用fmap'
和join
。 因此添加join
會使您的符號完整,但在許多情況下仍然不方便,因為您最終需要大量的join
。
但是,如果你從翻譯中刪除return
,你會得到一些與Idris'bang notation非常相似的東西:
在許多情況下,使用do-notation會使程序不必要地冗長,特別是在上面
m_add
情況下,立即使用值綁定一次。 在這些情況下,我們可以使用速記版本,如下所示:m_add : Maybe Int -> Maybe Int -> Maybe Int m_add xy = pure (!x + !y)
符號
!expr
表示應該計算表達式expr
然后隱式綁定。 從概念上講,我們可以想到!
作為具有以下類型的前綴函數:(!) : ma -> a
但是請注意,它不是真正的函數,只是語法! 在實踐中,子表達式
!expr
將在其當前作用域內盡可能高地提升expr
,將其綁定到新名稱x
,並將!expr
替換為x
。 表達式首先從左到右提升深度。 在實踐中,! - 注釋允許我們以更直接的方式編程,同時仍然給出關於哪些表達式是monadic的符號線索。例如,表達式:
let y = 42 in f !(g !(print y) !x)
被提升到:
let y = 42 in do y' <- print y x' <- x g' <- gy' x' fg'
討論了將其添加到GHC,但拒絕(到目前為止)。 不幸的是,我找不到討論它的線程。
這個怎么樣:
do a <- something
b <- somethingElse a
somethingFinal a b
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.