2013-04-04 23 views
25

GHC'lerin lexically scoped type variables'unu kullanmak isterseniz, explicit universal quantification'u da kullanmanız gerekir. ölçümü ile ilgisiKapsamlı tür değişkenler, açık alan adları gerektirir. Niye ya?

{-# LANGUAGE ExplicitForAll, ScopedTypeVariables #-} 

f :: forall a . [a] -> [a]  -- The `forall` is required here ... 
f (x:xs) = xs ++ [x :: a]  -- ... to relate this `a` to the ones above. 

bu aslında bir şey var mı, yoksa uzatma yazarlar sadece nereye için uygun bir işaretleyici olarak forall anahtar kelime coopt vermedi: O senin işlevlerin tip imzalar için forall bildirimleri eklemek zorunda olduğunu Yeni, geniş kapsam belirleme geçerlidir? Başka bir deyişle, neden forall'u her zamanki gibi bırakamıyoruz? İşlev gövdesindeki ek açıklamalardaki tür değişkenlerinin, işlev imzasındaki aynı ada sahip değişkenlere başvurduğu açıkça görülmez mi? Ya da yazım bir şekilde sorunlu veya belirsiz olur mu?

+1

Aşağıda kendi yanıtımı gönderdim, ama dikkate almadığım ek incelikler olup olmadığını merak ediyorum. ... – pash

+9

Haskell-98'in kapsamı genişlemediğinden, yalnızca forall tarafından sunulan kapsam değişkenlerine sahip olmak bir uzlaşmadır. Bu şekilde eski kod, ScopedTypeVariables'ı açarken hala çalışır. (Muhtemelen, Haskell her zaman kapsamlı değişkenler içermelidir.) – augustss

cevap

24

Evet, niceleyici anlamlıdır ve türlerin anlamlı olması gerekir.

İlk olarak, Haskell'de "niteliksiz" tip imzası diye bir şey olmadığına dikkat edin. forall olmadan imzalar gerçekten örtülü olarak ölçülür. Bu kod ...

f :: [a] -> [a]       -- No `forall` here ... 
f (x:xs) = xs ++ [x :: a]    -- ... or here. 

... gerçekten bu şu anlama gelir:

f :: forall a . [a] -> [a]    -- With a `forall` here ... 
f (x:xs) = xs ++ [x :: forall a . a] -- ... and another one here. 

Yani bu ne diyor anlamaya edelim. Önemli olan, f ve x imzalarında a olarak adlandırılan tip değişkenlerinin ayrı niceleyicileriyle bağlı olduğunu fark etmektir. Bu, bir ad paylaşmasına rağmen farklı değişkenleri oldukları anlamına gelir. Yani yukarıdaki kod bu eşdeğerdir:, artık açık farklılaşmış adlarıyla

f :: forall a . [a] -> [a] 
f (x:xs) = xs ++ [x :: forall b . b] -- I've changed `a` to `b` 

sadece f ve x için imzalar tip değişkenler ilgisiz, ama bu o x iddiaları için imza x can olduğunu Herhangi bir türünde var. Ancak, x, a'a bir bağımsız değişkene uygulandığında belirli bir türe sahip olması gerektiğinden, bu olanaksızdır. Ve aslında tip denetleyici bu kodu reddeder. f için imza tek forall ile Diğer taraftan

,

...

f :: forall a . [a] -> [a]    -- A `forall` here ... 
f (x:xs) = xs ++ [x :: a]    -- ... but not here. 

... x imzaya içinde af 's başında nicelik bağlanır imzası, bu a, f imzasında a adı verilen değişkenler tarafından temsil edilen türle aynı türü temsil eder.

+0

Görünüşe göre https://downloads.haskell.org/~ghc/7.8.2/docs/html/users_guide/other-type-extensions.html#scoped- tip-değişkenler, bu tür ifadeleri ifadelerde ve desen tipi imzalarda da yapmak mümkündür.ama desen tipi imzaları anlamıyorum. – CMCDragonkai

+0

ScopedTypeVariables'i etkinleştirir, ancak ExplicitForAll özelliğini etkinleştirmezseniz ne olur? O zaman "forall" yazamazsın. O zaman ScopedTypeVariables'in etkisi nedir? Yazdığım bir pasajda, ScopedTypeVariables, belirli bir değerin bir işlev gövdesinde "Char" tipi olduğunu bildirmesine izin verdi. ScopedTypeVariables olmasaydı, yazmam için bana izin vermedi. Herhangi bir tür değişkeni birleştirmeye çalışmadığımdan garip olan bu. – CMCDragonkai

+0

@CMCDragonkai, '-XScopedTypeVariables', -XExplicitForAll' olmadan temelde kullanışsızdır. Yarısı, ikincisini kurmayı unuttum ve saçlarımın 5 dakika boyunca yırtılmaya başladığını fark ettim. – pash