Запутанные типы в ghci

Вот мой код:

n = [(a,b) | a <- [1..5],b <- [1..5]]
calcBmis xs = [bmi | (w, h) <- xs,let bmi = w / h ^ 2]  

При попытке применить calcBmis в nЯ получаю следующую ошибку:

*Charana> calcBmis n

<interactive>:220:1:
    No instance for (Fractional Integer)
    arising from a use of ‘calcBmis’
    In the expression: calcBmis n
    In an equation for ‘it’: it = calcBmis n

Дальнейшее расследование в ghci:

*Charana> :t calcBmis
calcBmis :: Fractional t => [(t, t)] -> [t]
*Charana> :t n
n :: [(Integer, Integer)]

Я предполагаю, что список, который я создаю, имеет тип (Integer,Integer), но это не может быть обработано в calcBmis, который принимает только Fractional, Есть идеи, как решить эту проблему?

1 ответ

Решение

Ты можешь использовать div вместо (/):

calcBmis xs = [ bmi | (w,h) <- xs, let bmi = (w `div` h)^2 ]

Prelude> :t calcBmis
calcBmis :: Integral t => [(t, t)] -> [t]

Prelude> calcBmis n
[1,0,0,0,0,4,1,0,0,0,9,1,1,0,0,16,4,1,1,0,25,4,1,1,1]

как видите эта версия может справиться со всеми Integral значения - но, конечно, будет усекать (из-за div).

или вы можете сопоставить все с fromIntegral:

calcBmis xs = [ bmi | (w,h) <- xs, let bmi = (fromIntegral w / fromIntegral h)^2 ]

Prelude> :t calcBmis
calcBmis:: (Fractional t, Integral t1, Integral t2) => [(t1, t2)] -> [t]

Который тогда даст дробные значения:

Prelude> calcBmis n
[1.0,0.25,0.1111111111111111
,6.25e-2
,4.000000000000001e-2
,4.0
,1.0
,0.4444444444444444
, ... ]

в любом случае он будет работать со всеми входами, если они являются экземпляром Integral - вторая версия даже будет принимать пары разных интегралов;)

Другие вопросы по тегам