2010-09-01 4 views
0

Фрагмент followng содержит решение для exercise 3 on page 69 (напишите функцию mean, чтобы рассчитать среднее значение списка).Различное поведение Int и Integer?

При написании некоторых тестов QuickCheck, чтобы проверить, являются ли его результаты более или менее нормальными, я обнаружил, что в моей системе (ghc 6.12.3, Haskell Platform 2010.2.0.0 на 32-но Ubuntu 10.4) тесты работают на Integer входы, но не для Int единиц. Любая идея о том, почему?

import Test.QuickCheck 

-- From text and previous exercises 
data List a = Cons a (List a) 
      | Nil 
       deriving (Show) 

fromList  :: [a] -> List a 
fromList []  = Nil 
fromList (x:xs) = Cons x (fromList xs) 

listLength    :: List a -> Int 
listLength Nil   = 0 
listLength (Cons x xs) = 1 + listLength xs 

-- Function ``mean`` is the aim of this exercise 
mean    :: (Integral a) => List a -> Double 
mean Nil   = 0 
mean (Cons x xs) = (fromIntegral x + n * mean xs)/(n + 1) 
    where n = fromIntegral (listLength xs) 

-- To overcome rounding issues 
almostEqual  :: Double -> Double -> Bool 
almostEqual x y = (abs (x - y)) < 0.000001 

-- QuickCheck tests for ``mean`` 
prop_like_arith_mean :: (Integral a) => [a] -> Property 
prop_like_arith_mean xs = not (null xs) ==> 
          almostEqual 
          (mean (fromList xs)) 
          (fromIntegral (sum xs)/fromIntegral (length xs)) 

prop_sum :: (Integral a) => [a] -> Bool 
prop_sum xs = almostEqual 
       (fromIntegral (length xs) * mean (fromList xs)) 
       (fromIntegral (sum xs)) 

-- This passes: 
check_mean_ok = 
    quickCheck (prop_like_arith_mean :: [Integer] -> Property) >> 
    quickCheck (prop_sum :: [Integer] -> Bool) 

-- This fails: 
check_mean_fail = 
    quickCheck (prop_like_arith_mean :: [Int] -> Property) >> 
    quickCheck (prop_sum :: [Int] -> Bool) 

main = check_mean_ok >> 
     check_mean_fail 
+2

Полностью нерелевантный вопрос, но ваша функция 'mean' выглядит очень неэффективной для меня. Она вычисляет длину списка на каждом шаге в рекурсии, что означает, что эта функция будет перемещаться по списку намного больше, чем это необходимо. Существует много дискуссий о том, как оптимизировать это, попробуйте просмотреть арку haskell-cafe ives или читать сообщение блога Конала Эллиотта на тему «Красивые складки». –

+0

@John: Спасибо за комментарий: я нашел http://squing.blogspot.com/2008/11/beautiful-folding.html следующий пост Конала, и это было очень поучительно! –

+0

спасибо за эту ссылку. Приношу свои извинения оригинальному автору; Я был только знаком с последующим наблюдением Конала и, таким образом, не отдавал должное, когда это должно произойти. –

ответ

5

Int основан на реализации Int базовой системы, и, возможно, одни и те же нижние и верхние пределы как базовой системы (но, по крайней мере, диапазон [-2^29, 2^29 - 1]. Integer имеет произвольную точность, поэтому при использовании Int может возникнуть переполнение или недополнение.

+0

Спасибо, jball - я не думал о over-/underflow –

Смежные вопросы