爲什麼Clojure儘管如此強調功能範例,卻不使用monad來表示可選值?在我經常使用的函數式編程語言Scala中,使用Option
相當普遍。爲什麼在Clojure中Maybe/Option的使用不那麼普遍?
回答
Clojure不是靜態類型的,所以不需要嚴格的haskell(以及我收集的Scala)中必需的this/that /任何類型的聲明。如果你想返回一個字符串,你會返回一個字符串;如果你返回零,相反也沒關係。
「功能」並不完全對應於「嚴格編譯時鍵入」。它們是正交的概念,Clojure選擇動態類型。事實上,相當長一段時間,我無法想象如何實現map
等更高階的函數,並仍保留靜態類型。現在我對Haskell有一點(非常少的)經驗,我可以看到它是可能的,而且通常非常優雅。我懷疑,如果你在Clojure上玩了一段時間,你會有相反的經歷:你會意識到類型聲明不是必需的給你一種功能語言的權力。
你可能沒有得到我的問題。我的問題與類型聲明完全無關。 – missingfaktor 2011-04-30 06:10:28
根據我的經驗,無論所討論的語言是靜態類型還是動態類型,'Maybe' /'Option'都很有用。 – missingfaktor 2011-04-30 06:11:21
@missingfaktor:不,我認爲amalloy有一個點動態類型化語言經常使用某些值(如'nil')來表示「沒有這樣的事情」,但是這個值是不同的類型(在Scheme中,它是一個列表;在Ruby中,它是'NilClass'的唯一實例;我從來沒有使用過Clojure,但我想像這就像Scheme一樣)。沒有靜態類型系統,就沒有必要將結果提升到「可能」;這是隱含的,可以這麼說。我個人傾向於更喜歡Haskell/Scala的方式,但動態類型語言中的另一種方法沒有任何問題。 – 2011-04-30 11:09:46
也許/選項是一種類型。它與函數式編程無關。是的,一些語言(斯卡拉,哈斯克爾,ocaml)除了功能性也提供了一個非常強大的類型系統。人們甚至會說haskell它是一種帶有類型的編程。
其他(clojure,lisp)儘管它們是功能完備的語言,但它們的類型並不多。他們的重點是不同的,而Maybe/Option類型不適合。它在動態語言中根本不會給你太多。例如,對序列(列表,向量,地圖)進行操作的許多clojure函數將完全接受null(nil)並將其視爲空結構。
(計數爲零)會給你0。就像(計數[])
的Clojure不能被稱爲「編程與類型」,因而也許類型沒有太大的意義在裏面。
與@amalloy一起發表評論,作爲一種語言,Clojure不需要可選的返回值。
我對Scala並沒有做太多的工作,但Clojure並不需要知道返回類型的嚴格細節,以便能夠使用值。就好像一個Maybe monad被嵌入並且成爲正常Clojure評估的一部分,因爲如果在nil
上執行許多操作,則返回nil
。
我快速瀏覽了Clojure-Contrib庫,他們有一個monad package,你可能想看看。另一個真正讓我知道如何在Clojure中使用Monad的項目是Cosmin's tutorial on Monads in Clojure。正是這樣才能幫助我將Scala中更明確地陳述的功能作爲動態Clojure語言的一部分進行處理。
在Clojure中,nil punning提供了Scala & Haskell從Option &獲得的大部分功能。
**Scala** **Clojure**
Some(1) map (2+_) (if-let [a 1] (+ 2 a))
Some(1) match { (if-let [a 1]
case Some(x) => 2+x (+ 2 a)
case None => 4 4)
}
Scala的選項& Haskell的也許是應用型的兩個實例。這意味着你可以在理解中使用這些類型的值。例如,Scala支持:
for { a <- Some(1)
b <- Some(2)
} yield a + b
Clojure's for macro提供對seq的理解。與monadic理解不同,這個實現允許混合實例類型。
雖然Clojure的for不能用於在多個可能的nil值上編寫函數,但它的功能很簡單。
(defn appun [f & ms]
(when (every? some? ms)
(apply f ms)))
,把它:
(appun + 1 2 3) #_=> 6
(appun + 1 2 nil) #_=> nil
重要的是要記住,單子概念是不是類型是很重要的!類型系統可以幫助你執行規則(但即使Haskell也不能執行所有的規則,因爲它們中的一些(Monad定律)不能被類型系統完全表達出來)
Monads是關於構圖,這是一個非常在所有情況下,Monad都會跟蹤一些關於正在發生的事情的「額外上下文」......把它想象成一個盒子,可以保存當前值。到這個值,並且額外的上下文可以作爲一個正交的關注點演化
Maybe類型是關於將長序列的計算串聯在一起,而不必對失敗(這是「額外的上下文」)做任何說明。這是一種將「錯誤處理」移出計算的模式並進入Monad。你可以在一個Maybe上對一系列計算進行串聯,只要一個失敗,其餘的都會被忽略,最終的結果就是「無」。如果他們都成功了,那麼你的最終結果就是擁有結果值的monad。
這使您可以編寫糾纏得更少的代碼。
Clojure支持Monads,正如@deterb指出的那樣。
最後,Monad的解釋不需要先理解類別理論。這確實是Monad的全部內容。這是一個恥辱的大多數嘗試解釋混淆這與奧術數學。 – 2017-06-14 23:04:44
- 1. 爲什麼OODBMS不像RDBMS那麼普遍?
- 2. 爲什麼caliburn不像棱鏡那麼普遍?爲什麼只有少數人使用caliburn?
- 3. 爲什麼不能在Coq中使用普遍合格的假設?
- 4. 爲什麼clojure中的並行qsort比普通的實現慢?
- 5. LL(k)是什麼普遍的語言?
- 6. 爲什麼我不能在ApiController中使用普通視圖?
- 7. 爲什麼嵌套的div(Bootstrap例子)如此普遍?
- 8. 在Clojure中,爲什麼rand-int的使用如此複雜?
- 9. 爲什麼在Clojure中使用conj的列表需要撇號?
- 10. 爲什麼clojure的地圖println只能在repl中使用?
- 11. 什麼是Clojure中
- 12. 那麼Java中的XML有什麼用?
- 13. 什麼能力你需要在一個普遍應用
- 14. 那麼Coffescript使用什麼呢?
- 15. 爲什麼(#(+%1)3)工作但(#(%)3)在Clojure中不起作用?
- 16. 爲什麼使用ROLAP而不是普通的MySQL?
- 17. 爲什麼使用authentication_token而不是普通的認證過程?
- 18. 爲什麼我們在gcc中使用-lpcap,那是什麼意思?
- 19. clojure pmap - 爲什麼我不使用所有的核心?
- 20. 爲什麼這些Clojure列表不同?
- 21. 爲什麼rand()在fork之後不是那麼隨機的?
- 22. 爲什麼在Clojure中重複使用會導致崩潰?
- 23. 在Clojure中爲什麼要使用:只有[]
- 24. 爲什麼在這個代碼中有那麼多「\」......它有什麼用法..?
- 25. 爲什麼或者爲什麼不在C++中使用memset?
- 26. 爲什麼在這個函數中必須使用getchar()?我不明白爲什麼它在那裏
- 27. 爲什麼我不能使用那樣的匿名方法?
- 28. 爲什麼我的師在那裏?
- 29. 爲什麼在Clojure中使用merge-with而不是簡單的'merge'?
- 30. 爲什麼這不是那種方式?
我要指出丹尼爾爲什麼選擇Scala使用Option [T]的優秀答案;也許答案應該先閱讀它。 - http://stackoverflow.com/questions/2079170/why-optiont/2079758#2079758 – 2011-04-30 17:47:37