Фрагмент 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
Полностью нерелевантный вопрос, но ваша функция 'mean' выглядит очень неэффективной для меня. Она вычисляет длину списка на каждом шаге в рекурсии, что означает, что эта функция будет перемещаться по списку намного больше, чем это необходимо. Существует много дискуссий о том, как оптимизировать это, попробуйте просмотреть арку haskell-cafe ives или читать сообщение блога Конала Эллиотта на тему «Красивые складки». –
@John: Спасибо за комментарий: я нашел http://squing.blogspot.com/2008/11/beautiful-folding.html следующий пост Конала, и это было очень поучительно! –
спасибо за эту ссылку. Приношу свои извинения оригинальному автору; Я был только знаком с последующим наблюдением Конала и, таким образом, не отдавал должное, когда это должно произойти. –