在haskell,Fractional和Int中输入类型

时间:2012-03-10 02:43:52

标签: haskell

我编写了一个函数(应该)获取无限的布尔列表并计算前n个元素的真值与假值之比:

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

不幸的是,这不起作用:

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.

我尝试进行转换,但这不起作用:

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

它正在编译,但是一旦我尝试调用该函数,我就会收到错误:

*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

有什么建议吗?

2 个答案:

答案 0 :(得分:11)

你在错误的地方转换。尝试在整个fromRationalfoldr周围粘贴n

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

哦,您的boolToInt功能与fromEnum专用Bool相同。

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

您尝试做的根本问题是您对prob的第一个参数强加了相互冲突的要求。您使用toInteger约束nIntegral,但在/中的使用要求它为Fractional,并且没有类型Integral }和Fractional

答案 1 :(得分:0)

BoolEnum的一个实例,因此boolToInt已提供fromEnum。此外,foldr正在执行sum,因此整个功能可以简化为:

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

我们可以抽象出用于计算均值的代码(尽管这必须确定列表的长度,我们已经知道):

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

prob n = mean . map fromEnum . take n