2011-09-10 6 views
23

ben liste halinde sadece eşitler yarıya Haskell bir işlev yapıyorum ve hiç bir sorun yaşıyorum. Derleyiciyi çalıştırdığımda, bir int bölümlendirmesi yapamayacağınız ve kesirli bir int tür bildirime ihtiyacım olduğundan şikayetçidir. Tip bildirimini süzülmeye çalıştım, ancak yeni bir hata oluşturdu. Fonksiyonun kodunu aşağıya ekledim ve herhangi bir yardım biçimini umuyordum.Bölümü Haskell

halfEvens :: [Int] -> [Int] 
halfEvens [] = [] 
halfEvens (x:xs) | odd x = halfEvens xs 
       | otherwise = x/2:halfEvens xs 

Okuma için teşekkür ederiz. tamsayı bölme yerine

+1

Bu durumda x' div' 2 olmasını istiyorsunuz. Başka birinin doğru olduğumu doğrulamasına izin vereceğim (% 100 emin değilim) ve daha eksiksiz bir açıklama yapalım. – MatrixFrog

cevap

31

kullanımı div:

halfEvens :: [Int] -> [Int] 
halfEvens [] = [] 
halfEvens (x:xs) | odd x = halfEvens xs 
       | otherwise = x `div` 2 : halfEvens xs 

(/) fonksiyon, tip sınıfında Kesirli olan bağımsız değişkenleri gerektirir, ve standart bölme yapar. div işlevi, türü İntegral sınıfında olan ve tam sayı bölmesi gerçekleştiren argümanlar gerektirir.

Daha doğrusu, div ve negatif sonsuzluğa doğru mod yuvarlak. Onların kuzenleri, quot ve rem, integer division in C gibi davranır ve sıfıra doğru yuvarlanır. (Tarihi verilmediği haftanın gününü hesaplarken mesela) modüler aritmetik yaparken div ve modquot ve rem biraz daha hızlı iken (Sanırım), genellikle doğrudur.

GHCi biraz gezinerek oynamak:

> :t div 
div :: Integral a => a -> a -> a 
> :t (/) 
(/) :: Fractional a => a -> a -> a 
> 3/5 
0.6 
> 3 `div` 5 
0 
> (-3) `div` 5 
-1 
> (-3) `quot` 5 
0 
> [x `mod` 3 | x <- [-10..10]] 
[2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1] 
> [x `rem` 3 | x <- [-10..10]] 
[-1,0,-2,-1,0,-2,-1,0,-2,-1,0,1,2,0,1,2,0,1,2,0,1] 
+0

Yardımlarınız için çok teşekkür ederim. – D347th

+0

Evet, daha hızlıdır, çünkü makine talimatı bu eğilimindedir. Her iki tür bölme yönergesi olan NS32k işlemcisi hariç. – augustss

+1

ghc, 2 gücüyle sağa kaydırmaya göre bölmeyi optimize eder mi? N bitlerin aritmetik bir sağa kayması 2 ** n'ye bölünecek, ancak negatif sonsuza doğru yuvarlanacaktır (eğer -1 eğer sağa kayıyorsa, hala -1 elde edersiniz). 0'a doğru yuvarlamak için, kaymadan önce giriş negatifse (2 ** n) -1 eklemeniz gerekir. Bu durumda, 'div'' – pat

0

Ben map kullanarak kodu basitleştirmek olacağını eklemek gerekir.

HalfIfEven n 
    | even n = n `div` 2 
    | otherwise = n 

halfEvens = map halfIfEven 
+0

Ama bu size aynı sonucu vermiyor. Orijinal kod oranları ortadan kaldırır, sizinki değil. En basit ihtimalle muhtemelen 'halfEvens = harita (\ 'div \' 2) olur. filtre bile – semicolon