[英]Haskell: Would “do” notation be useful for contexts other than monads?
我們都喜歡do
,我很好奇,如果這種替代語法在理論上可能在monad世界之外有用。 如果是這樣,它會簡化哪些其他類型的計算? 例如,為Applicative提供相同的東西是否有意義?
我的感覺是許多Haskell程序員根本不喜歡do
,並且當你不需要Monad
的全部功能時,支持使用Applicative
一個常見論點是組合器<$>
, <*>
等允許非常清晰簡潔的編碼風格。
即使是一元的代碼,很多人喜歡使用=<<
明確,而不是do
記號。 camccann 對你之前關於<*>
問題的回答給出了這個偏好的奇妙論據。
我傾向於使用do
編寫我的第一個草稿,然后在我修改時用組合器替換。 這只是我自己的(中)的經驗和品味的問題:通常最容易為我勾畫的事情了更迫切的方式(這是更方便do
),但我覺得非do
代碼通常是漂亮。
對於箭頭,在另一方面,我不能沒有使用想象proc
和命令do
。 元組剛剛變得如此丑陋。
它可能有助於考慮,就do
記號本身,就是它的功能確實不錯。 正如特拉維斯·布朗指出的那樣,我之前曾提倡使用Monad
和相關類型的“函數應用程序”樣式,但也有另一面: 有些表達式根本無法在直接函數應用程序中寫得干凈利落風格 。 例如,以下內容可以迅速使應用風格笨拙:
將這樣的函數編寫為單個表達式通常需要多個嵌套的lambdas,或者是一種荒謬的混淆廢話,它使無點樣式成為壞名稱。 另一方面, do
塊提供語法糖,以便通過嵌入式控制流輕松嵌套中間結果的范圍。
通常你可能會提取這樣的子表達式並將它們放在where
子句或其他東西中,但是由於普通值與函數應用程序形成一個monad (>>=)
- 也就是Identity
monad - 你可以想象寫下這樣一個函數一個do
阻止相反,盡管人們可能會看着你笑。
除了作用域/綁定之外, do
塊為你do
的另一件事就是將子表達式鏈接在一起的運算符。 想象一下“在這個塊中使用這個函數組合這些表達式”,然后讓編譯器填入空白的其他情況並不難。
在簡單的情況下,表達式都具有相同的類型,將它們放在一個列表然后折疊它也很有效 - 例如,使用unwords
和unlines
以這種方式構建字符串。 do
的好處是它將表達式與通用結構和兼容(但不完全相同)類型相結合。
事實上,同樣的總的原則是從的“成語支架”符號的真正Applicative
紙:在哪里do
塊使用新行的Elid到一元結構,成語支架利用並列提起的Elid功能應用。 Arrow
的proc
符號也類似,其他概念也可以用這種方式干凈地表達,例如:
雖然將這些中的許多變成單個類型或完整的Monad
實例並不太難,但對於一般概念來說,擁有一個統一的,可擴展的語法糖可能會很好。 肯定有一個共同的線程將所有這些和更多的東西捆綁在一起,但這是一個與語法無關的更大的話題......
該do
記號基本上是說:“根據需要轉化為lambda表達式和分發的方式>>=
字里行間”。
當顯而易見的是什么運算符用於推動所有事情時,省略並利用“換行符”運算符是很好的。
可編程換行將是處理材料列表,應用鏈等的好方法。 要制作列表,您還需要一個“可編程的外部”。 實際上,您可以只取三個有意義的位並使它們全部可重載:
do
。 do
。 do
。 然后,你可能不應該把它do
了。 也許它應該只是一個支架。
成語括號構成了考慮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
但是,詞匯范圍規則有點令人不安。
Applicative
有(更有限,更緊湊)成語括號,請參閱應用程序編程與效果 ,第4頁。我相信Conor McBride的Strathclyde Haskell環境實現了這些。
我不知道如何推廣這些特殊的語法,但也許我沒有給它足夠的思考。
還有適合有單子的推廣do
記號-參數化的單子。 通過sigfpe查看Beyond Monads。 用法示例:
test1' = do put 1
x <- get
put (show x)
y <- get
return (x,y)
這是一個“狀態monad”,它首先存儲一個數字,然后是一個字符串。
GHC中有一個預處理器可以為Arrows做到這一點: http : //www.haskell.org/ghc/docs/6.12.2/html/users_guide/arrow-notation.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.