Casting type in haskell, Fractional and Int

I wrote a function that (should) take an infinite list of booleans and calculate the ratio of True to False values ​​over the first n elements:

prob n list = foldr (+) 0 (map boolToInt (take n list)) / n
    where boolToInt b
        | b == True = 1
        | otherwise = 0

      

unfortunately what doesn't work:

No instance for (Fractional Int)
  arising from a use of `/'
Possible fix: add an instance declaration for (Fractional Int)
In the expression: foldr (+) 0 (map boolToInt (take n list)) / n
In an equation for `prob':
    prob n list
      = foldr (+) 0 (map boolToInt (take n list)) / n
      where
          boolToInt b
            | b == True = 1
            | otherwise = 0
Failed, modules loaded: none.

      

I tried to do the conversion, but that doesn't work either:

prob n list = foldr (+) 0 (map boolToInt (take (fromIntegral (toInteger n)) list)) / n
    where boolToInt b
        | b == True = 1
        | otherwise = 0

      

It compiles, but as soon as I try to call the function, I get the error:

*Main> prob 50 toCoin1
<interactive>:1:6:
Ambiguous type variable `a0' in the constraints:
  (Num a0) arising from the literal `50' at <interactive>:1:6-7
  (Integral a0) arising from a use of `prob' at <interactive>:1:1-4
  (Fractional a0) arising from a use of `prob' at <interactive>:1:1-4
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `prob', namely `50'
In the expression: prob 50 toCoin1
In an equation for `it': it = prob 50 toCoin1

      

Any suggestions?

+3


source to share


2 answers


You are converting to the wrong place. Try to just stick fromRational

around everyone foldr

and n

.

prob n list = fromIntegral count / fromIntegral n
    where count = foldr (+) 0 (map boolToInt (take n list))
          boolToInt b
            | b == True = 1
            | otherwise = 0

      

Oh, and your function is boolToInt

identical fromEnum

, specialized for Bool

s.



prob n list = fromIntegral count / fromIntegral n
    where count = foldr (+) 0 (map fromEnum (take n list))

      


The main problem with what you were trying to do is to impose conflicting requirements on the first argument prob

. Your use is toInteger

limited n

as Integral

, but its use /

required it to be Fractional

, and there is no type that both Integral

and Fractional

.

+11


source


Bool

- this is a copy Enum

, therefore it is boolToInt

already provided fromEnum

. It also foldr

does sum

, so the whole function can be simplified to:

prob n list = (fromIntegral . sum . map fromEnum . take n) list / fromIntegral n

      



We could abstract from the code to compute the average (although this would have to determine the length of the list we already know):

mean xs = (fromIntegral . sum) xs / (fromIntegral . length) xs

prob n = mean . map fromEnum . take n

      

0


source