0

Вот мой код:Смешение типов в 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. Любая идея, как решить эту проблему?

ответ

2

вы можете использовать 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 - вторая версия будет даже принимать пары разных интегралов;)

+0

красивый, спасибо – Charana