Reputation: 223
I've written a function that (should) takes 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 that's not working:
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 make a conversion, but that isn't working either:
prob n list = foldr (+) 0 (map boolToInt (take (fromIntegral (toInteger n)) list)) / n
where boolToInt b
| b == True = 1
| otherwise = 0
It's compiling, but as soon as I try to call the function I get an 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?
Upvotes: 3
Views: 7822
Reputation: 12749
Bool
is an instance of Enum
, so boolToInt
is already provided by fromEnum
. Also, the foldr
is doing sum
, so the whole function can be simplified to:
prob n list = (fromIntegral . sum . map fromEnum . take n) list / fromIntegral n
We could abstract out the code for computing the mean (although this will have to determine the length of the list, which we already know):
mean xs = (fromIntegral . sum) xs / (fromIntegral . length) xs
prob n = mean . map fromEnum . take n
Upvotes: 0
Reputation: 185871
You're converting at the wrong place. Try just sticking a fromRational
around the entire 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 boolToInt
function is identical to fromEnum
specialized to Bool
s.
prob n list = fromIntegral count / fromIntegral n
where count = foldr (+) 0 (map fromEnum (take n list))
The fundamental problem with what you tried to do was you imposed conflicting requirements on the first argument to prob
. Your use of toInteger
constrained n
to be Integral
, but its use in /
required that it be Fractional
, and there's no type that's both Integral
and Fractional
.
Upvotes: 11