Soru Ortak kullanımda Int vs?


Alış / geri dönüşün ortak şekli gibi görünüyor Int (yani ByteString.hGet ve Data.List.length) Bu tür olguların çoğunun sadece pozitif sayıları ele alabilmesi nedeniyle, Haskell modelinin güçlü bir şekilde aşağıdan gelen türler kullanılmasına aykırı olduğu düşünülmektedir. Kullanmak daha iyi olmaz mı Wordya da bu işlevlerin kısmi bir nedeni var mı Int?


32
2017-09-14 21:21


Menşei


Kısmen tarihsel kazada, kısmen alt seviyedeki yapıların ve fonksiyonların altında kaldığı için Int argümanlar (yine tarihsel kaza ile, en azından kısmen). Örneğin, GHC'nin dizi uygulama kullanımının tüm düşük düzeyli endeksleme işlemleri Int# endeksleri. - Daniel Fischer
@DanielFischer bir cevap gibi görünüyor. Bir tane ekleyebilir misiniz? :) - singpolyma
Daha da iyisi, neden dünyada yok ki Natural türüne karşılık gelen Integer? >: [Bu bana sürekli bir sıkıntı kaynağıdır. - C. A. McCann
@ C.A.McCann: Özellikle can sıkıcı çünkü kendinizi iyi bir şekilde tanımlayamıyorsunuz. fromInteger ya tuhaf davranmak zorundaydı - argümanının mutlak değerini döndürmek ya da bir şey - ya da kısmi olmak zorundaydı. Negatif değişmezler için size bir tür hata verecek sayısal bir yazı yazmak için açık bir yol yoktur. (Belki de reddetmenin anlamını değiştirmek için yeniden yazılabilir sözdizimi ile? Bilmiyorum ...) - Tikhon Jelvis
@TikhonJelvis: Haha. Literaller gittikçe, fromInteger sadece beni daha fazla tahriş eden pozitif değerlere uygulanır. Eğer negate ve fromInteger ayrı tip sınıfları vardır, literals gayet iyi çalışır. Sorun senin fromNatural hala yanlış adlandırılmış ve bunu negatif gayri menkullere uygulayabilirsiniz ... - C. A. McCann


Cevaplar:


Haskell tipi sistemin ifadesinin, kullanıcıları tanımladıkları varlıklara kesin tipler tahsis etmeleri konusunda teşvik ettiği doğrudur. Bununla birlikte, tecrübeli Haskellers, kişinin nihai tip hassasiyeti arasında (ki bunun yanında Haskell tipi sistemlerin mevcut sınırları göz önüne alındığında her zaman elde edilemeyen) ve rahatlık arasında bir denge kurması gerektiğini kolayca anlayacaktır. Kısacası, kesin tipler sadece bir nokta için yararlıdır. Bu noktanın ötesinde, çoğu zaman sadece fazladan bürokrasiye neden olurlar.

Bir örnekle problemi gösterelim. Faktoriyel fonksiyonu ele alalım. Hepsi için n 1'den büyük, faktöriyel n bir çift sayıdır ve 1'in faktörü çok ilginç değildir, o yüzden onu görmezden gelelim. Bu nedenle, Haskell'deki faktoriyel fonksiyonun uygulanmasının doğru olduğundan emin olmak için, yalnızca işaretsiz çift tam sayıları temsil edebilen yeni bir sayısal tür tanıtmak cazip gelebilir:

module (Even) where

newtype Even = Even Integer

instance Num Even where
  ...
  fromInteger x | x `mod` 2 == 0 = Even x
                | otherwise = error "Not an even number."

instance Integral Even where
  ...
  toInteger (Even x) = x

Bu veri türünü yapıcıyı dışa aktarmayan, soyut hale getirecek ve onu ilgili tüm tip sınıflarının bir örneği haline getirecek bir modül içinde mühürleriz. Int bir örneğidir. Şimdi faktörü aşağıdaki imzayı verebiliriz:

factorial :: Int -> Even

Türü factorial Sadece döndüğünü söylememizden daha kesin Int. Ama bu defizining'i bulacaksın factorial Böyle bir tip ile gerçekten oldukça can sıkıcı, çünkü bir çoğaltan bir versiyonu (bir çift veya tek) çarpar Int bir ile Even ve üretir ve Even. Dahası, gereksiz çağrıları tanıtmanız gerekebilir. toInteger bir çağrı sonucu factorial müşteri kodunda, az kazanç için önemli bir dağınıklık ve gürültü kaynağı olabilir. Ayrıca, tüm bu dönüşüm fonksiyonları potansiyel olarak performans üzerinde olumsuz bir etki yaratabilir.

Başka bir problem ise, yeni ve daha kesin bir tür sunarken, çoğu zaman kütüphane işlevlerinin çoğunu kopyalamak zorunda kalmanızdır. Örneğin, türü tanıtıyorsanız List1 a boş olmayan listelerin, daha sonra, Data.List zaten sağlar, ancak [a] bir tek. Elbette, bu fonksiyonlar bir tane yapabilir ListLike tür sınıfı. Ancak, hemen hemen her tür adhoc tipi sınıf ve diğer kazanlarla sonuçlanacaksınız.

Son bir nokta, birinin dikkate almaması gerektiği Word imzasız bir varyantı olmak Int. Haskell raporu gerçek boyutunu bırakır Int belirtilmemiş ve sadece bu türün [- 2 aralığında tamsayıları temsil edebileceğini garanti eder29, 229 - 1]. Türü Wordbelirtilmemiş genişlikte işaretsiz tamsayılar sağlandığı söylenir. Uygun herhangi bir uygulamada, bir genişliğin Word bir genişliğine karşılık gelir Int.

Her ne kadar aşırı tür çoğalmasına karşı bir noktaya dikkat etsem de, bir tür Natural Doğalların güzel olabilir. Nihayetinde, Haskell'in ek olarak doğal sayılar için özel bir türe sahip olması gerekir. Int, Integerve çeşitli Word*  türleri, büyük ölçüde bir tat meselesidir. Ve şimdiki durum, büyük bir ihtimalle tarihin bir kazasıdır.


27
2017-09-14 22:42



Haskell 2010 raporunda §23.1'e göre, Word ile aynı boyutta imzasız bir integral türüdür. Int." - Stefan


Aynı mantık C'deki gibi de geçerlidir. Daha kesin tiplerin kullanılmasının nedeni hataların önlenmesidir. Hatalar, bu durumda, anlamlı olmayan yerlerde negatif sayıları kullanmaya çalışmak gibi. Ama davranışları Word gereğinden fazla veya az unsigned int C içinde etrafı sarmaktır. Eğer negatif bir sayı kullanmaya çalışırsanız Word (veya unsigned int) bekleniyor, derleyiciye bağırıyorsunuz, hatta çalışma zamanında bir istisna bile alamıyorsunuz. Büyük bir pozitif sayı elde edersiniz. Başka herhangi bir (“meşru”) büyük pozitif sayıdan ayırt etmenin hiçbir yolu yoktur!

Şuna bak:

Prelude Data.Word> -1 :: Word
4294967295

Yapmak imkansız hatalar yapmak yerine, onları tespit etmek imkansız hale getirdiniz. İle Int (ve int) En azından negatif değerleri manuel olarak kontrol etme olanağına sahipsiniz. İle Word ve unsigned int, Hiçbir şeyin yok.

Neyin değerli olacağı, bir istisna atarak aşırıya veya az akmaya tepki veren işaretsiz bir türdür. Bu hala hataları imkansız hale getirmez, ama onları tespit etmeyi kolaylaştırır. Bununla birlikte, bir performans maliyetine varacaktır. * Derleme zamanında bunları yönetmenin mümkün olup olmadığını bilmiyorum, ancak kolay görünmüyor.

* En azından x86, her işlemden sonra ekstra bir talimat gerektirir! - Aşırı veya az akış olup olmadığını kontrol etmek için. Güzel olsa da, "bedavaya" yapan bir mimarinin olup olmadığını bilmiyorum. Ya da belki de kayan nokta sayıları gibi ayırt edici bir NaN değeri (belki yerine en negatif sayı) temsil edilemez değerleri belirtmek için kullanılacaktır ...


21
2017-09-15 16:09



Ne? Haskell Int tam olarak aynı sorunu var (3::Int)^2^2^2^2 = -5843219465185787903 - Jeff Burdges


İlk tahminim, imzasız aritmetiğin, dikkat etmeyecekseniz aptal hatalara neden olacak bazı sorunlara sahip olmasıdır:

Prelude Data.Word> let x = 0 :: Word in if x - 1 > x then "Ouch" else "Ohayoo"
"Ouch"

Doğru görünen polimorfik fonksiyonlarda bazı sorunlar olacaktır:

Prelude Data.Word> let f acc x y = if x <= y then f (acc + 1) x (y - 1) else acc
Prelude Data.Word> :t f
f :: (Num a1, Num a, Ord a) => a1 -> a -> a -> a1

Standart uzunluk fonksiyonu kullanarak:

Prelude Data.Word> let len' x = if null x then 0 else 1 + len' (tail x) :: Int
Prelude Data.Word> :t len'
len' :: [a] -> Int

Prelude Data.Word> f 0 0 (len' [1,2,3])
4

Ve bir uzunluğun fonksiyonunu tekrar kullanmak Word:

Prelude Data.Word> let len x = if null x then 0 else 1 + len (tail x) :: Word
Prelude Data.Word> :t len
len :: [a] -> Word

Prelude Data.Word> f 0 0 (len [1,2,3])
...diverges...

Ve tabii ki, eğer bu işlevler geri döndüyse Word yerine Int, dönüştürmeyi sürdürme ihtiyacını siz tanıştırıyorsunuz. Wordiçine Intdiğer ortak yerlerde kullanmak için.


5
2017-09-14 23:00