2011-09-10 9 views
23

Tworzę funkcję w Haskell, która dzieli tylko o połowę na liście i mam problem. Kiedy uruchamiam kompilatora, narzeka, że ​​nie możesz wykonać podziału int i że potrzebuję ułamkowego deklaracji typu int. Próbowałem zmienić deklarację typu na float, ale to tylko wygenerowało kolejny błąd. Zawarłem poniższy kod funkcji i miałem nadzieję na jakąkolwiek formę pomocy.Dywizja w Haskell

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

Dziękuję za przeczytanie.

+1

Myślę, że chcesz x 'div' 2 w tym przypadku. Pozwolę komuś innemu potwierdzić, że mam rację (nie w 100% jestem pewien) i udzielę pełniejszego wyjaśnienia. – MatrixFrog

Odpowiedz

31

Zastosowanie div, który wykonuje dzielenie całkowitej:

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

Funkcja (/) wymaga argumentów, których typ jest w klasie frakcyjną i przeprowadza standardową podział. Funkcja div wymaga argumentów, których typ jest w klasie Integral, i wykonuje dzielenie liczby całkowitej.

Dokładniej, div i mod w obie strony w kierunku ujemnej nieskończoności. Ich kuzyni, quot i rem, zachowują się jak integer division in C i zaokrąglają w kierunku zera. div i mod są zwykle poprawne podczas wykonywania arytmetyki modułowej (na przykład przy obliczaniu dnia tygodnia z datą), podczas gdy quot i rem są nieco szybsze (chyba).

Bawiąc się trochę w GHCi:

> :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

Dziękuję bardzo za pomoc. – D347th

+0

Tak, quot jest szybszy, ponieważ tak właśnie robi instrukcja komputera. Z wyjątkiem procesora NS32k, który posiadał oba rodzaje instrukcji podziału. – augustss

+1

Czy ghc optymalizuje dzielenie przez potęgę 2 na przesunięcie w prawo? Arytmetryczne przesunięcie w prawo o n bitów zostanie podzielone przez 2 ** n, ale zaokrąglone zostanie w kierunku ujemnej nieskończoności (jeśli przesuniesz w prawo -1, otrzymasz -1). Aby zaokrąglić w kierunku 0, musisz dodać (2 ** n) -1, jeśli dane wejściowe są ujemne przed zmianą. W tym przypadku 'div' powinno być szybsze niż" quot " – pat

0

Dodam, że za pomocą map uprości kod.

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

halfEvens = map halfIfEven 
+0

Ale to nie daje tego samego wyniku. Oryginalny kod usuwa kursy, twoje nie. Najprostszy prawdopodobnie byłby 'halfEvens = map (\ div \ 2). filter even' – semicolon