簡體   English   中英

類型同義詞的類限制?

[英]Class restriction for type synonyms?

我想做類似的事情:(在偽代碼中;這不會編譯)

type Num a => Vector2d = (a,a)

或者可能

type Num a => Vector2d a = (a,a)

但我不能這樣做。

在閱讀之后,我有一種感覺,要實現這一點,我需要RankNTypes擴展或forall關鍵字,但我無法圍繞這個...

有人可以幫忙嗎?

編輯:我管理,而是通過“猜測語法”:解決方案是,確實與RankNTypes

type Vec =  forall a. Num a => (a,a)

這有效,但具有RankNTypes擴展名

type Vec = Num a => (a,a)

同樣有效。 有什么區別, Num a =>約束(看起來很自然)如何與n級類型相關?

所以問題仍然存在,但我正在尋找解釋,而不是解決方案。

type Vec = forall a. Num a => (a, a)

是一樣的

type Vec = Num a => (a, a)

原因是GHC在最頂層的類型變量范圍中隱式引入了沒有相應forall每個類型變量,例如:

const :: a -> b -> a
const :: forall a b. a -> b -> a -- the same thing

在大多數情況下,類型同義詞只是語法上的便利,因此每當您在類型簽名中看到Vec時,您只需將括號括在其定義周圍並替換:

Vec -> Vec -> Integer
-- equals:
(forall a. Num a => (a, a)) -> (forall a. Num a => (a, a)) -> Integer

有一個奇怪的例外,你不能盲目地替換類型。 如果你有這樣的類型同義詞:

type Vec a = Num a => (a, a) 

然后Num約束在替換后浮動到最外層范圍:

vec = (100, 100) :: Vec Integer
-- vec has now type "(Integer, Integer)"

和相同類型變量合並的多個約束:

addVec :: Vec a -> Vec a -> Vec a
addVec (a, b) (c, d) = (a + c, b + d)
-- addVec has now effectively type "Num a => (a, a) -> (a, a) -> (a, a)

在上面的例子中,類約束沒有引入更高的排名,因為約束被綁定到外部范圍中的變量。 但是,當我們在數據構造函數中使用同義詞時,約束將變為隱式(存在)字典:

type Foo a = Num a => a 
data Bar a = Bar (Foo a) -- equals "data Bar a = Bar (Num a => a)"
-- requires ExistentialQuantifiaction or GADTs to compile

-- and of course, any data constructor blocks the outwards floating of the constraint:
type Baz = a -> (Foo a, ()) -- requires ImpredicativeTypes.

因此,總而言之,類型同義詞中這些約束的行為相當不穩定。 我們需要RankNTypesRank2Types來編寫它們,但這似乎更像是一個實現工件而不是其他任何東西。 我們可以爭辯說語法可以用來向類型引入量詞,這種類型證明了RankNType要求,但我們同樣可以說編譯器應該檢測是否有新的量詞是合理的,並相應地進行(如它已經完成了引入的存在...)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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