SORU
4 Mart 2010, PERŞEMBE


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
4 Mart 2010, PERŞEMBE


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

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • We've moved!

    We've moved!

    7 Ocak 2008
  • ImBluecams

    ImBluecams

    25 Kasım 2012
  • Techmoan

    Techmoan

    31 Mayıs 2009