簡體   English   中英

Haskell:除了monad之外,“do”符號對於上下文有用嗎?

[英]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的另一件事就是將子表達式鏈接在一起的運算符。 想象一下“在這個塊中使用這個函數組合這些表達式”,然后讓編譯器填入空白的其他情況並不難。

在簡單的情況下,表達式都具有相同的類型,將它們放在一個列表然后折疊它也很有效 - 例如,使用unwordsunlines以這種方式構建字符串。 do的好處是它將表達式與通用結構和兼容(但不完全相同)類型相結合。

事實上,同樣的總的原則是從的“成語支架”符號的真正Applicative紙:在哪里do塊使用新行的Elid到一元結構,成語支架利用並列提起的Elid功能應用。 Arrowproc符號也類似,其他概念也可以用這種方式干凈地表達,例如:

  • 組合數據結構,例如合並某種類型的結果集,省略合並功能
  • 其他函數應用程序習慣用法,例如參數優先“前向管道”樣式,忽略了應用程序運算符
  • 並行計算,省略結果聚合函數

雖然將這些中的許多變成單個類型或完整的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環境實現了這些。

我不知道如何推廣這些特殊的語法,但也許我沒有給它足夠的思考。

BlazeHtml使用do -notation實際上它只是一個Monoid (雖然包裹為Monad以便能夠使用do )。

因此Monoid s的類似符號在那里很有用。

如果你看看我的游戲“保衛國王”的代碼,那么我也做了很多mconcat ,就像BlazeHtml一樣,我會受益於一個漂亮的語法。

還有適合有單子的推廣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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM