2016-04-04 11 views
4

Her türlü tür ()'un aynı olduğunu kabul etmek güvenli midir? Yani, tip güvenliği kırmak için aşağıdakiler kullanılabilir mi?Birim tipleri eşittir postular güvenli midir?

-- Bad postulate 
unitsEqual :: (x ::()) :~: (y ::()) 
unitsEqual = unsafeCoerce (Refl :: '() :~: '()) 

cevap

5

Bu ghc 7.8.3 altında güvensiz (aşağıdaki kodu bakınız). User2407038 ifadesiyle, aşağıdakiler GHC 7.10.3 tarafından reddedilmiştir. Şaşırtıcı olmayan bir şekilde, bu veri ailesi, tip denetçisinin yasaklamak için değiştirildiğinden yeterince kötüydü. Hala bunun 7.10.3 altında gerçekleşmesinin bir yolu olup olmadığını görmeye çalışıyorum.

{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE TypeOperators #-} 
{-# LANGUAGE KindSignatures #-} 
{-# LANGUAGE DataKinds #-} 

module UnitsEqual where 
import Unsafe.Coerce 
import Data.Type.Equality 

data family Yeah (a ::()) b c 
data instance Yeah '() b c = Yeah { yeah :: b } 
data instance Yeah a b c = Nope c 

-- Entirely valid 
castYeah :: x :~: y -> Yeah x p q -> Yeah y p q 
castYeah Refl x = x 

-- Bad postulate 
unitsEqual :: (x ::()) :~: (y ::()) 
unitsEqual = unsafeCoerce (Refl :: '() :~: '()) 

-- Oh no! This doesn't actually cast, but 
-- it's horrible enough. It consistently produces 
-- either segmentation faults or nonsense, 
-- whether the types are the same or not. 
uc :: a -> b 
uc a = yeah $ castYeah unitsEqual (Nope a) 

Ben Void yaşayan sıkışmış/sahte türlerinin herhangi ayırt etmek bariz yolu yoktur çünkü

voidsEqual :: (a :: Void) :~: (b :: Void) 

önermeyi güvenli olduğunu, ancak, inanmak .

+2

Bu ghc 7.10.3 tarihinde Yeah' 'için "Çakışan aile örneği bildirimleri" verir. – user2407038

+0

@ user2407038, ilginç! 7.8.3'ün altında test ettim. 7.10.3'te çalışmam için bunu düzeltip değiştiremeyeceğimi görmeliyim. – dfeuer

1

Sorumluluk reddi: Bu yanıt esasen tahmin çalışmasıdır, çünkü bu davranış gerçekten beni şaşırttı ve ben hala tam olarak typechecker içinde Any semantiklerinden çok emin değilim. o belirsiz bir tip değişken bulur ve Any bunu somutlaştırır Nope a tipi hesaplar zaman Yeah muhtemelen reddedilmesi gerektiğini göz ardı senin örnekte

. Bu, örn. length [] çalışması.

Sen ghc 7.10 kabul edilen bir GADT, Aynı işlemleri :, eşitlik '() ~ Any

data Yeah (a ::()) b c where 
    Yeah :: b -> Yeah '() b c 
    Nope :: c -> Yeah Any b c 

ikinci durumda bir işlev

yeah :: Yeah '() b c -> b 
yeah (Yeah a) = a 
yeah (Nope _) = error "???" 

ihtiyaç uc yazmak için ise verdiğim gibi, örneğin

okay :: 'True :~: 'False -> x 
-- okay Refl = error "???" -- Compiler rejects this case 
okay x = case x of 

ama bu bir: 'True ~ 'False, Int ~ Bool vb typechecker bu gerçekleri bilir!

really :: Any :~: '() -> x 
really Refl = error "???" -- Perfectly valid pattern match 

Aslında bu işlevi çağırmak olamaz:

>:t really Refl 

<interactive>:1:8: Warning: 
    Couldn't match type `Any' with '() 
    Expected type: Any :~: '() 
     Actual type: '() :~: '() 
    In the first argument of `really', namely `Refl' 
    In the expression: really Refl 

ve süre uc typechecks (tanım değişmedi) artık kırar:

>uc 'a' :: Int 
*** Exception: ??? 

O typechecker yapar gibi görünüyor '() :~: Any'un iskan edilmediğine inanmayın, çünkü bu, çünkü typechecker dahili olarak böyle bir kanıt üretmesine izin verilir, ancak kullanıcı hala sağa sola Kendileri yazıyor.

Tüm söylemek gerekirse: Bence Any varsa, unitsEqual sesli ve Any varoluşundan kaynaklanır.Any :~: '() - - kar¸ıt tarafından açıkça yanlış olduğu görünüyor ama x ~ yx ve y farklı türleri vardır ve ne x veya yAny yalnızca trivially yanlış olduğunu söylüyor Any için özel typechecker kural var gibi görünüyor.

voidEqual eşit çürük olduğu için Any :: Void, Any Any :: Void, Any Any Any :: Void vb

+0

'Herhangi bir özel durum (artık) değil. Artık "type family Any :: k where {}" olarak tanımlandı. Bu "sıkışmış tip aile" dir. – dfeuer

+0

Sanırım GHC 8.0 ya da benzerleri var mı? 7.10.3 ile bile geçerli bir sözdizimi görünmüyor. – user2407038

+0

Sanırım öyle. Herhangi bir örneği hiçbir zaman yapmazsanız, aynı özellikleri açık tip bir aile ile alabilirsiniz. – dfeuer

İlgili konular