我在理解不同類型的多態性時遇到問題,特別是關於OCaml。我明白,多態性允許OCaml中的多種類型表示爲'a,但我不明白不同類型的多態性是什麼。
如果有人可以給我一個相對低級的語言解釋,那就太棒了! 特設,參數,包含/子類型OCaml中的多態性 - 特設,參數化,包含/子類型
回答
我其實並不認爲這種問題特別適合堆棧溢出的優點。有關於類型的完整書籍。事實上,我建議讀皮爾斯的Types and Programming Languages,我發現它非常有啓發性和令人愉快。
作爲一個快速回答(主要基於我從皮爾斯記得的:-),這裏是我對這些術語的看法。
參數多態性是指具有自由變量的類型,其中變量可以被任何類型替換。函數List.length
具有這樣的類型,因爲它可以找到任何列表的長度(不管元素的類型如何)。
# List.length;;
- : 'a list -> int = <fun>
一個約OCaml中的美妙的事情是,它不僅支持類型,像這種情況,推斷他們。給定一個函數定義,OCaml爲函數推斷最一般的參數多態類型。
子類型是類型之間的關係。 A型Ť是類型ü的一個亞型如果T的所有實例都還ü的實例(但不一定反之亦然)。 OCaml支持子類型,也就是說,它允許程序將T的值作爲其超類型的值和。但是,程序員必須明確地詢問這一點。
# type ab = [ `A | `B ];;
type ab = [ `A | `B ]
# type abc = [`A | `B | `C ];;
type abc = [ `A | `B | `C ]
# let x : ab = `A;;
val x : ab = `A
# let y : abc = x;;
Error: This expression has type ab but an expression was expected
of type abc. The first variant type does not allow tag(s) `C
# let y : abc = (x :> abc);;
val y : abc = `A
在這個例子中,類型式ab
是abc
類型的子類型,和x
具有類型ab
。可以使用x
作爲abc
類型的值,但必須使用:>
類型運算符進行顯式轉換。
Ad-hoc多態性是指程序員爲特定情況定義的多態性,而不是從基本原理派生的。 (或者至少這就是我的意思,也許其他人會用不同的術語。)一個可能的例子是OO繼承層次結構,其中對象狀態的實際類型不需要以任何方式關聯,只要方法有適當的關係。
ad-hoc多態性(IMHO)的關鍵觀察在於程序員是否能夠正常工作。因此,它並不總是工作。這裏基於基本原理的其他類型的多態性實際上不能失效。在處理複雜系統時,這是一種令人欣慰的感覺。
下面是一個近似值。
即席多態通常指能夠用不同類型聲明相同的名稱(通常是函數),例如, SML中的+ : int -> int -> int
和+ : float -> float -> float
。這些功能是不同的,它們可以以完全不同的方式工作,但編譯器或解釋器根據上下文選擇適當的函數。我無法想象OCaml中的任何ad-hoc多態性。然而,這在C++和Java中很常見。
參數多態性是指單個函數可以與任何類型的參數一起工作,因爲沒有試圖查看該參數的結構。例如,cons : 'a -> 'a list -> 'a list
可以將任何類型的值v
預加到相同類型的值列表中,因爲cons
v
的結構(佈局)是什麼或它支持哪些操作並不重要。在C語言中,cons
不需要「取消引用」指針,或者對v
執行任何特定於v
的實際類型的操作。請注意,與ad-hoc多態性不同,cons
的對所有類型的行爲都是相同的。因此,參數和特定多態性是彼此天然「相反」的一種方式。參數多態性是OCaml中絕大多數多態性實例的原因。
亞型多態性是當您可以使用t
類型的值時,預期類型爲u
的值。這可能是因爲t
類型支持u
類型的所有操作,或者因爲t
的結構可用於需要u
的地方。這樣做的例子可以是子類別(也許總線可以用於車輛的任何地方)或多態變體(您可以使用'A | 'B
,其中'A | 'B | 'C
預計)。根據註釋
注
編輯,然而,子類型必須OCaml中明確要求。例如,如果您有一個功能f : u -> int
,並且您想將其應用於v : t
,其中t
是u
的子類型,則必須編寫f (v :> u)
。 (v :> u)
語法是一種類型的強制。
OCaml還支持行多態,這是一種帶約束的參數多態的形式。如果f
改爲f : #u -> int
(用於對象類型)或f : [< u] -> int
(用於多態變體),則語法代表類型變量,類似於'a
,但其只能用各自的「子類型」u
(在限制意識到他們可以分別支持更多的字段/更少的構造函數)。然後,你可以做f v
沒有脅迫。 OCaml自動推斷對包含多態變量和對象的多個表達式使用行多態的類型,但是如果要創建簽名,則必須明確地寫出類型。
行多態性有更多的用法和注意事項。我忽略了實際的行變量和附加語法,只描述了看起來像有限量化的東西(如Java泛型)。關於行多態性,其名稱和/或其形式主義的更詳細和準確的討論,可能是最好的保存單獨的問題。
OCaml中的多態變體(和對象)不是*子類型,而是基於參數多態的行多態。子類型僅在添加類型轉換(在OCaml中顯式)時纔會出現。其餘絕對正確。此外,adhoc多態的一個很好的例子是Haskell中的類型(和模塊蘊涵...)。 – Drup
大多數都是正確的 - 但是你必須明確地寫出用於子類型的強制轉換纔是OCaml的細節。我不想讓概念答案複雜化。它*是真實的,多態總和和對象是支持子類型關係的類型。也有涉及這些類型的行多態性,並且它覆蓋了一些子類型的使用情況,而不需要OCaml中的明確強制,這是另一回事。並且,行多態性當然不是多態變體和對象「所」 - 只是他們支持的一件事。我會在一張紙條上工作。 – antron
IDENT是多形性:
# let ident x = x;;
val ident : 'a -> 'a = <fun>
# ident 1;;
- : int = 1
# ident "ok";;
- : string = "ok"
# ident [];;
- : 'a list = []
# ident List.length;;
- : '_a list -> int = <fun>
# ident ident;;
- : '_a -> '_a = <fun>
倍也:
# open List;;
# fold_left (+) 0 [1;2;3];;
- : int = 6
# fold_left (^) "" ["1";"2";"3"];;
- : string = "123"
# fold_left (fun a (x,y) -> a+x*y) 0 [(1,2);(3,4);(5,6)];;
- : int = 44
- 1. OCaml中的參數化類型
- 2. 什麼是C++中的參數化和包含多態性
- 3. Haskell中的抽象數據類型與參數化多態性
- 4. 參數化類和多態性
- 5. 多態性GTEST類型參數
- 6. 多態遞歸對象類型OCaml中
- 7. OCaml中的線性類型
- 8. C++中的子類型多態性
- 9. C++中的多態性,子類型?
- 10. Coq中的子類型多態性
- 11. 函子與多個參數OCaml中
- 12. 如何在OCaml中創建具有多個參數的類型?
- 13. 爲什麼OCaml使用多態變體的子類型?
- 14. SerializationException:類型不包含在序列化的類型設置
- 15. 。包含()派生類的特定類型?
- 16. 參數化類型的類型參數
- 17. 參考自類型參數化性狀
- 18. 多態性,參變多態性,特殊多態性
- 19. 使用類作爲可能包含也可能不包含其他類型參數的類型參數
- 20. 單子記錄包含多態函數
- 21. 動態設置泛型類型參數
- 22. OCaml序列化與類型
- 23. OCaml變量類型泛化
- 24. OCaml的仿函數取多態性變異型
- 25. 多態性/子類型違規?
- 26. 類型參數化或結構子類型或
- 27. 在參數化類中混合泛型特徵而不復制類型參數
- 28. 泛型類型多態性
- 29. 「參數字典包含非空參數的非空類型」?
- 30. 從包含多種類型的列表中刪除特殊類型C#
當然,你的意思是特設多態,不是即席*亞型*? – antron
謝謝,我修好了。 –
但ad-hoc多態不是這個。本例中描述的是一個對象系統,其中對象的佈局不參與評估子類型關係(即一種類型是否是另一種類型的子類型)。特設多態不是子類型的一種形式。 – antron