我知道什麼類型的協方差和逆變。我的問題是爲什麼我在研究Haskell(與Scala相反)時還沒有遇到這些概念的討論?爲什麼沒有關於Haskell(與Scala或C#相反)中的共同和反對方差的討論?
Haskell視圖類型與Scala或C#相比有一個根本性的區別,我想闡明它們之間的區別。
或者,也許我錯了,我只是還沒有學會足夠的哈斯克爾尚未:-)
我知道什麼類型的協方差和逆變。我的問題是爲什麼我在研究Haskell(與Scala相反)時還沒有遇到這些概念的討論?爲什麼沒有關於Haskell(與Scala或C#相反)中的共同和反對方差的討論?
Haskell視圖類型與Scala或C#相比有一個根本性的區別,我想闡明它們之間的區別。
或者,也許我錯了,我只是還沒有學會足夠的哈斯克爾尚未:-)
主要有兩個原因:
但是,這些概念確實適用 - 例如,fmap
對Functor
實施的提升操作實際上是協變的;在類別理論中使用術語co-/contravariance來討論函子。 contravariant
package爲逆變函數定義了一個類型類,如果你看一下實例列表,你會看到爲什麼我說它不太常見。
也有地方的想法隱含顯示出來,如何手動轉換工作 - 各種數字型類定義的轉換和從基本類型,如Integer
和Rational
,模塊Data.List
包含的一些標準功能的通用版本。如果你看看the types of these generic versions,你會看到Integral
限制(給出toInteger
)用於逆變位置類型,而Num
約束(給出fromInteger
)用於協變位置。
我認爲逆變與可變性之間沒有關係。事實上,可變性導致不變性。反變換的例子是函數輸入,'Ord'和'Eq'(當然是它們的等價物),其中沒有一個甚至有數據要被突變。 – 2012-02-16 17:08:55
@ DanielC.Sobral:寫入一個可變引用是逆變的,是函數輸入的特例。因此,儘管簡單的數據類型通常允許協變性,但允許逆變的類型往往表示匯或輸出,除非涉及某種副作用,否則這些類型可能是微不足道的。不過,讀取和寫入操作的可變引用必然是不變的。 – 2012-02-16 18:06:25
@丹尼爾與可變性相關的逆變可以在[with function]中看到(http://hackage.haskell.org/packages/archive/snap/0.7/doc/html/Snap-Snaplet.html#v:with)提供通過Snap Framework的Snaplet API。它的設計恰恰是爲了讓「易變」狀態的層級能夠被輕鬆操縱。 – mightybyte 2012-02-16 18:09:21
Haskell中沒有「子類型」,所以協變和逆變都沒有任何意義。在斯卡拉,你有例如Option[+A]
與子類Some[+A]
和None
。你必須提供協方差註釋+
來說Option[Foo]
是Option[Bar]
if Foo extends Bar
。由於子類型的存在,這是必要的。
在Haskell中,沒有子類型。在哈斯克爾Option
等效,叫Maybe
,有這樣的定義:
data Maybe a = Nothing | Just a
類型變量a
永遠只能是一個類型的,所以它沒有進一步的信息是必要的。
如上所述,Haskell沒有子類型。但是,如果您正在查看類型類,可能不清楚如何在沒有子類型的情況下工作。
類型類指定類型的謂詞,而不是類型本身。所以當Typeclass有一個超類(例如Eq a => Ord a)時,並不意味着實例是子類型,因爲只有謂詞是繼承的,而不是類型本身。
另外,co-,contra-和in-variance在數學的不同領域意味着不同的東西(參見Wikipedia)。例如,在函數中使用了協變和逆變這兩個術語(這反過來在Haskell中使用),但這些術語意味着完全不同的東西。術語不變式可以在很多地方使用。
這已經有一段時間了,但我似乎記得這段視頻中關於co/contra-variance的一些函數/ haskellish對話框:http://channel9.msdn.com/shows/Going+Deep/E2E-Brian-Beckman-and -Erik-Meijer-CoContravariance-in-Physics-and-Programming-2-of-2/ – steamer25 2012-02-16 19:43:02