2013-02-18 3 views
2

Im пытается выяснить, в чем проблема. Кажется, что-то не так с типами, но одно и то же выражение работает отлично.Тип ошибки, связанной с долями

Вот код:

a = [9, 4, 12, 0, -6, 16] :: [Int] 

qsort:: [Int] -> [Int] 
qsort [] = [] 
qsort [x] = [x] 
qsort xs = (qsort l)++(qsort r) 
    where m = (realToFrac(sum xs))/(realToFrac(length xs)) 
      l = filter (<=m) xs 
      r = filter (>m) xs 

main::IO() 
main = do 
     print (show (qsort a)) 

Он бросает:

main.hs:7:36: 
    No instance for (Fractional Int) 
     arising from a use of `/' 
    Possible fix: add an instance declaration for (Fractional Int) 
    In the expression: (realToFrac (sum xs))/(realToFrac (length xs)) 
    In an equation for `m': 
     m = realToFrac (sum xs)/(realToFrac (length xs)) 
    In an equation for `qsort': 
     qsort xs 
      = (qsort l) ++ (qsort r) 
      where 
       m = realToFrac (sum xs)/(realToFrac (length xs)) 
       l = filter (<= m) xs 
       r = filter (> m) xs 

Но что хорошо работает:

a = [9, 4, 12, 0, -6, 16] :: [Int] 
main::IO() 
main = do 
    print (show ( (realToFrac(sum a))/(realToFrac(length a)) )) 
+0

Альтернативное решение: удалить 'realToFrac' и использование' '' сумма Xs quot' длина xs''; 'quot' - это деление типа« Интеграл »(который обрезает/округляет к нулю,' div' округляется к -infinity), а так как 'xs :: [Int]', 'sum xs' и' length xs' имеют одинаковые type ('Int'), так что работает без конверсий. –

ответ

6

Ваше m определение дает ряд типов Fractional. Однако вы сравниваете m с Int в определении l и r, что смешивает компилятор. Ниже будет делать трюк:

a = [9, 4, 12, 0, -6, 16] :: [Int] 

qsort:: [Int] -> [Int] 
qsort [] = [] 
qsort [x] = [x] 
qsort xs = (qsort l)++(qsort r) 
    where m = realToFrac(sum xs)/(realToFrac(length xs)) 
      l = filter ((<=m) . fromIntegral) xs 
      r = filter ((>m) . fromIntegral) xs 

main::IO() 
main = do 
     print (show (qsort a)) 
+0

Очень приятно, спасибо :) – crimsonlander

5

realToFrac(sum xs)/(realToFrac(length xs)) делает работу, но его результатом является дробным числом. Таким образом, в вашем коде m есть дробное число. Но вы сравниваете m с элементами в своем списке, которые являются Интс. Поскольку вы можете сравнивать только значения одного типа, а Ints - не дробные числа, это вызывает ошибку типа.

Для устранения проблемы вы можете использовать целочисленное деление (div) или преобразовать целые числа в список в дробные числа, прежде чем сравнивать их с m.

+0

Да, вы правы. Но тогда, почему я могу сделать это 4.5 <5 без ошибок? – crimsonlander

1

Вы можете использовать x в качестве стержня. Совместимость списка образцов «qsort (x: xs)» здесь очень помогает.

a = [9, 4, 12, 0, -6, 16] :: [Int]                      

qsort:: [Int] -> [Int]                         
qsort [] = []                           
qsort (x:xs) = (qsort l) ++ [x] ++ (qsort r)                   
    where l = filter (<=x) xs                      
      r = filter (>x) xs                       

main::IO()                            
main = putStrLn $ show $ qsort a 

-- *Main> main                           
-- [-6,0,4,9,12,16] 

Альтернативный синтаксис, а также: http://hpaste.org/81793

+2

Твоя неправильная запись @crimsonlander. Quicksort работает, помещая каждый элемент поворота в правильное место после завершения процесса фильтрации. Следовательно, [x] должен находиться в середине (qsort l) и (qsort r) (его правильно отсортированная позиция) –

+0

Извините, не заметила некоторых деталей :) – crimsonlander

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