İşlevsel programlamada varolan türler gerçekten kötü uygulama olarak kabul edilmez. Sizi tetikleyen şey, varoluşların en çok kullanılan kullanımlarından birinin , birçok insanın kötü bir uygulama olduğuna inandığı varoluşlu tip sınıf antipattern olduğunu düşünüyorum.
Bu model çoğu zaman aynı tip sınıfı uygulayan heterojen şekilde yazılmış elemanların bir listesinin nasıl bulunacağı sorusuna bir cevap olarak ortaya çıkar. Örneğin, Show
örnekleri olan bir değerler listesine sahip olmak isteyebilirsiniz :
{-# LANGUAGE ExistentialTypes #-}
class Shape s where
area :: s -> Double
newtype Circle = Circle { radius :: Double }
instance Shape Circle where
area (Circle r) = pi * r^2
newtype Square = Square { side :: Double }
area (Square s) = s^2
data AnyShape = forall x. Shape x => AnyShape x
instance Shape AnyShape where
area (AnyShape x) = area x
example :: [AnyShape]
example = [AnyShape (Circle 1.0), AnyShape (Square 1.0)]
Bunun gibi kod ile ilgili sorun şudur:
- Üzerinde gerçekleştirebileceğiniz tek faydalı işlem
AnyShape
alanını almaktır.
AnyShape
Şekil türlerinden birini türüne getirmek için yapıcıyı kullanmanız gerekir AnyShape
.
Görünen o ki, bu kod parçası size gerçekten bu kısa olandan bir şey elde etmiyor:
class Shape s where
area :: s -> Double
newtype Circle = Circle { radius :: Double }
instance Shape Circle where
area (Circle r) = pi * r^2
newtype Square = Square { side :: Double }
area (Square s) = s^2
example :: [Double]
example = [area (Circle 1.0), area (Square 1.0)]
Çok yöntemli sınıflar söz konusu olduğunda, aynı efekt genellikle daha basit bir şekilde "yöntemlerin kaydı" kodlaması kullanılarak gerçekleştirilebilir - benzer bir sınıf sınıfı kullanmak yerine Shape
, alanlarını " Shape
türlerinin " yöntemleri "olan bir kayıt türü tanımlarsınız. ve çevrelerinizi ve karelerinizi Shape
s'ye dönüştürecek işlevleri yazarsınız .
Ancak bu, varoluşsal türlerin sorun olduğu anlamına gelmez! Örneğin, Rust'ta , insanların genellikle bir özellik üzerinde varoluşsal bir tür olarak tanımladığı, özellik nesneleri (Rust'in tür sınıflarının sürümleri) tanımladığı özellik nesneleri adı verilen bir özelliği vardır . Eğer varoluşsal sınıflar Haskell'de bir kamaştırıcı ise, bu, Rust'un kötü bir çözüm seçtiği anlamına mı geliyor? Hayır! Haskell dünyasındaki motivasyon, gerçekten prensip değil, sözdizimi ve kolaylıktır.
Bu koyarak bir daha matematiksel bir yolu olduğunu işaret edilir AnyShape
ve yukarıdan tipi Double
vardır izomorfik -orada aralarında "kayıpsız dönüşüm" (bit kayan nokta hassas için tasarruf, iyi) 'dir:
forward :: AnyShape -> Double
forward = area
backward :: Double -> AnyShape
backward x = AnyShape (Square (sqrt x))
Yani, kesinlikle konuşursak, birini seçip diğerini seçerek herhangi bir güç kazanmıyor ya da kaybetmiyorsunuz. Bu, seçimin kullanım kolaylığı veya performans gibi diğer faktörlere dayanması gerektiği anlamına gelir.
Ve varoluşsal türlerin bu heterojen listelerin dışında başka kullanımları olduğunu aklınızda bulundurun, bu yüzden bunların olması iyi bir şey. Örneğin, ST
harici olarak saf fakat dahili olarak hafıza mutasyon işlemlerini kullanan fonksiyonlar yazmamıza izin veren Haskell'in türü, derleme zamanında güvenliği sağlamak için varoluşsal türlere dayanan bir teknik kullanır.
Genel cevap şu ki, genel bir cevap yok. Varoluşsal türlerin kullanımları yalnızca bağlamda değerlendirilebilir - ve hangi dillerin ve sözdiziminin farklı diller tarafından sağlandığına bağlı olarak cevaplar farklı olabilir.