回答
您可以使用ExistentialQuantification
或GADTs
,但都不會做你想要的。您將永遠無法使用兩個Point2D
值進行算術運算。所有你知道的內容是,他們是一些 Num的實例。您正在告訴編譯器放棄關於它們的所有其他信息。這意味着您要告訴編譯器放棄任何可能具有的信息,即一對Point2D
值包含相同的類型。如果沒有這些信息,您將無法對兩個Point2D
的值進行任何算術運算。
這幾乎肯定不是你想要的。例如,你不能寫一個distance
函數。對於這種有限的類型你有什麼可能的用途?關於你所能做的所有事情是把他們的內容轉換爲String
。
編輯:
我想我明白你在做什麼。你只是想確保Point2D中的所有內容都是一個數字。我不認爲你真的想要類型擦除。
在這種情況下,我會去與GADT版本,其中一個非常重要的變化:
{-# LANGUAGE GADTs #-}
data Point2D a where
Point :: (Num a) => a -> a -> Point2D a
這樣做的最終結果是,你只能使用Point
構造具有相同的兩個值Num的實例,但不會丟失類型。此外,由於使用了GADTs
,構造函數Point
上的模式匹配爲您恢復了Num上下文,這基本上就是您期望的。
但我認爲這裏最重要的不是丟棄內容的類型。這樣做使得該類型基本上不可能合作。
爲數據成員恢復實例上下文似乎只在數據類型(使用`(Point a b)`或使用記錄字段名稱`Point {x = a,y = b}`)進行模式匹配時才起作用。但有什麼辦法可以讓這個字段訪問功能?也就是說,當用像`(x p)`這樣的表達式來訪問`Point`` p`時。 – Lii 2016-06-09 14:14:49
是,但您必須認識到約束的含義與通常的泛型不同。
通常情況下,像仿製藥type Foo a = (a, a)
意味着
爲各類
a
,Foo a
由兩a
的
然而,在你的榜樣,需要短語是不同的:
對於索姆e型
a
,Point2D
由兩a
的
或
有一個類型
a
該Point2D
由
因此,通用的類型不是通用(適用於所有類型...),但是存在(它存在某種類型...)。在GHC,我們可以通過extenstion
{-# ExistentialQuantification #-}
在本article on the topic描述允許這樣。您的代碼,畢竟是
data Point2D = forall a . Num a => Point a a
{-# LANGUAGE GADTs #-}
data Point2D where
Point :: (Num a) => a -> a -> Point2D
當然!
這應該做你想要什麼:
{-# LANGUAGE GADTs #-}
data Point2D a where
Point :: Num a => a -> a -> Point2D a
p :: Num a => a -> a -> Point2D a
p = Point
sumP :: Point2D a -> Point2D a -> a
sumP (Point a b) (Point c d) = a + b + c + d
您還可以使用existensials,但你不能做後它的模式匹配的數據什麼。
- 1. 在簽名中約束構造函數
- 2. 爲通用參數指定構造函數約束
- 3. LINQ2SQL實體構造函數約束
- 4. 指定類型約束約束
- 5. 類型參數構造函數簽名約束
- 6. 在通用約束中通過構造函數傳遞參數
- 7. 在C#中有參數約束的泛型構造函數嗎?
- 8. 約束 - 派生類必須有一個默認構造函數
- 9. 工廠方法構造函數的類型約束
- 10. 在對象構造函數或工廠中檢查約束?
- 11. 在子類構造函數中的接口類函數指針
- 12. 泛型類型的構造函數約束或只是檢查我的泛型類型構造函數中的約束?
- 13. 構造函數指向perl6中的類
- 14. 具有異構構造函數約束的C++工廠模式
- 15. 與約束定製領域構造
- 16. 在與超類構造函數不同的子類中定義構造函數?
- 17. 您可以在類型約束參數上設置匹配構造函數嗎?
- 18. '對匹配指定綁定約束的類型的構造函數的調用引發異常
- 19. 構造具有度約束
- 20. 在構造函數中指定重複的泛型類型?
- 21. 如何在案例類中指定多個構造函數?
- 22. 在C++類構造函數中的函數指針
- 23. 如何對構造函數的參數進行約束
- 24. 如何通用約束添加到非通用類的構造函數在C#
- 25. 在構造函數中調用類成員的構造函數
- 26. 在構造函數中調用不同類的構造函數?
- 27. 構造函數應該指定參數
- 28. 構建循環中的函數約束
- 29. 使用類/構造函數的指導
- 30. 在Xcode上指定約束
一般來說,最好將您的類型約束放在實際需要的地方。這不是數據類型,而是需要Num類型的方法,所以應該在那裏聲明。類型系統將負責其餘部分。 – amccausl 2011-01-27 06:45:58