Basit bir 'ortalama' fonksiyon Haskell tür sinir bozucu
Etrafta acemi Haskell ile oynuyorum, ve ortalama bir fonksiyon yazmak istedim. Dünyadaki en basit şey gibi görünüyordu değil mi?
Yanlış.
Haskell'ın sistem türü genel sayısal bir tür üzerinde çalışan ortalama yasaklar gibi görünüyor - bu İntegralleri veya Fractionals, ama ikisini bir listesini bir liste üzerinde çalışmak için alabilirim.
İstiyorum:
average :: (Num a, Fractional b) => [a] -> b
average xs = ...
Ama sadece alabilirim:
averageInt :: (Integral a, Fractional b) => [a] -> b
averageInt xs = fromIntegral (sum xs) / fromIntegral (length xs)
ya
averageFrac :: (Fractional a) => [a] -> a
averageFrac xs = sum xs / fromIntegral (length xs)
ve ikinci bir iş gibi görünüyor. Bir değişken geçmek için çalışıyorum kadar.
*Main> averageFrac [1,2,3]
2.0
*Main> let x = [1,2,3]
*Main> :t x
x :: [Integer]
*Main> averageFrac x
<interactive>:1:0:
No instance for (Fractional Integer)
arising from a use of `averageFrac ' at <interactive>:1:0-8
Possible fix: add an instance declaration for (Fractional Integer)
In the expression: average x
In the definition of `it': it = averageFrac x
Görünüşe göre, Haskell türleri hakkında çok seçici. Çok mantıklı. Ama her ikisi de olabilir [Num]
RealFrac bariz bir uygulama mi kaçırdım?
Kesirli bir giriş geldiğinde şok değil Fractionals içine İntegral zorlamak için bir yolu var mı?
Bir şekilde Either
either
sayısal dizi herhangi bir tür üzerinde çalışacak, polimorfik ortalama fonksiyon gibi kullanmak var mı?
Haskell tür sistem düpedüz şimdiye kadar varolan bu işlevini engelliyor mu?
Haskell Matematik öğrenmeye öğrenme gibi. Gerçekten karmaşık ve teori dağlar dayanıyor, ve bazen herhangi bir bilgi ... sıcak bir şekilde kabul olacak mindbogglingly bile yeterince ifade soru bilmiyorum karmaşık doğru yani.
(Ayrıca Dipnot: bu Ödev bir sorun kapalı dayanır. Herkes averageFrac, yukarıda, tam puan alır kabul eder, ama Ayrılmaz VE Kesirli diziler iki) iş yapmak için bir yol olduğunu bir sinsi bir şüphe var
CEVAP
Yani temelde, türünü ( / ) ile sınırlı konum:
(/) :: (Fractional a) => a -> a -> a
BTW, ayrıca Veri istiyorum.Liste.genericLength
genericLength :: (Num i) => [b] -> i
Yani nasıl bir şey daha genel fromİntegral kaldırma hakkında:
import Data.List
average xs = realToFrac (sum xs) / genericLength xs
sadece Gerçek bir kısıtlama (Tamsayı, Tamsayı, kayan nokta, Çift) vardır
average :: (Real a, Fractional b) => [a] -> b
Herhangi bir Kesirli herhangi bir Gerçek alacak.
Ve Haskell tüm posterler polimorfik sayısal rakamları tarafından yakalandığını unutmayın. 1 bir tamsayı değil, herhangi bir sayı.
Gerçek sınıf, yalnızca bir yöntem sağlar: bir rasyonel sınıf Sayı değeri açmak için yeteneği. Burada ihtiyacımız olan tam da bu.
Ve böylece,
Prelude> average ([1 .. 10] :: [Double])
5.5
Prelude> average ([1 .. 10] :: [Int])
5.5
Prelude> average ([1 .. 10] :: [Float])
5.5
Prelude> average ([1 .. 10] :: [Data.Word.Word8])
5.5
Nasıl Haskell, basit bir beşgen kullan...
Nasıl bir değişken variadic bir işlevi...
2013 4 - Ne kadar Sinir bozucu Bildiri...
c tamsayı->std::string dönüştürme. ...
Haskell: yardımcı fonksiyon adı neden ...