我想实现这笔钱。我遇到了关于类型签名的问题。
这就是Haskell的样子。
crowdWrong :: (Fractional b, Integral b) => b -> b
crowdWrong m = crowdWrong' m m
crowdWrong' :: (Fractional b, Integral b) => b -> b -> b
crowdWrong' m 1 = ((0.49) ^ (m-1)) * (0.51) * (choose m 1) * (0.98)
crowdWrong' m i = ((0.49) ^ (m-i)) * ((0.51) ^ i) * (choose m i) * (0.98)
+ (crowdWrong' m (i - 1))
choose :: Integer -> Integer -> Integer
choose n 0 = 1
choose 0 k = 0
choose n k = (choose (n-1) (k-1)) * n `div` k
GHCi的输出是:
untitled.hs:5:55:
Could not deduce (b ~ Integer)
from the context (Fractional b, Integral b)
bound by the type signature for
crowdWrong' :: (Fractional b, Integral b) => b -> b -> b
at untitled.hs:(5,1)-(7,42)
`b' is a rigid type variable bound by
the type signature for
crowdWrong' :: (Fractional b, Integral b) => b -> b -> b
at untitled.hs:5:1
In the first argument of `choose', namely `m'
In the second argument of `(*)', namely `(choose m 1)'
In the first argument of `(*)', namely
`((0.49) ^ (m - 1)) * (0.51) * (choose m 1)'
Failed, modules loaded: none.
我不知道如何解决这个问题,我想这会更容易。
编辑:
所以现在我有了这个:
crowdWrong :: Num b => Integer -> b
crowdWrong m = crowdWrong' m m
crowdWrong' :: Num b => Integer -> Integer -> b
crowdWrong' m 1 = ((0.49) ^ (m-1)) * (0.51) * (choose m 1) * (0.98)
crowdWrong' m i = ((0.49) ^ (m-i)) * ((0.51) ^ i) * (choose m i) * (0.98)
+ (crowdWrong' m (i - 1))
choose :: Integer -> Integer -> Integer
choose n 0 = 1
choose 0 k = 0
choose n k = (choose (n-1) (k-1)) * n `div` k
但是,GHCi仍然抱怨。
untitled.hs:5:48:
Could not deduce (b ~ Integer)
from the context (Num b)
bound by the type signature for
crowdWrong' :: Num b => Integer -> Integer -> b
at untitled.hs:(5,1)-(7,42)
`b' is a rigid type variable bound by
the type signature for
crowdWrong' :: Num b => Integer -> Integer -> b
at untitled.hs:5:1
In the return type of a call of `choose'
In the second argument of `(*)', namely `(choose m 1)'
In the first argument of `(*)', namely
`((0.49) ^ (m - 1)) * (0.51) * (choose m 1)'
Failed, modules loaded: none.
答案 0 :(得分:7)
您的代码基本上是正确的,但您为各个部分请求的类型不匹配。
choose
必须接受并返回Integer
s。这本身就可以,但是......
crowdWrong'
必须能够接收并返回 b
和Fractional
的任何类型Integral
。 Integer
只是一种具体类型(并且不是Fractional
的实例,用于启动)。这就是你得到的错误:~
是Haskell如何拼写类型相等,所以“无法推断(b ~ Integer)
”意味着b
≠Integer
。请注意,这与Java和其他OO语言不同;类型签名(例如crowdWrong' :: (Fractional b, Integral b) => b -> b -> b
表示crowdWrong'
必须能够接收并返回任何此类b
,而不是某些此类{ {1}}。 (它被称为参数多态,它就像泛型/模板。)
这个错误让你咬了两次。第一个问题是b
期望choose
个参数,但您已经传递了Integer
和m
,它们是任意类型i
。这里最简单的解决方法就是制作b
和m
i
s,无论如何看起来(看方程式)都是正确的。您使用Integer
和m
的唯一其他地方是i
的指数,其类型为(^)
。换句话说,(^) :: (Integral b, Num a) => a -> b -> a
的左侧和右侧不需要具有相同的类型。
第二个问题是(^)
会返回choose
结果,但您将其乘以小数。您可以使用Integer
来解决此问题,fromInteger :: Num a => Integer -> a
允许您在Num
中构建任何类型的Integer
ber。因此,代替choose m 1
,您可以编写fromInteger (choose m 1)
(或者,想象一下,fromInteger (m `choose` 1)
;反引号允许您编写任何函数中缀)。这甚至会编译!然而...
没有Fractional
和Integral
类型,因此您无法调用这些功能。 Fractional
类型类用于类似有理数的事物,而Integral
类型类用于类似整数的事物。 (这就是为什么Fractional
有(/)
,Integral
有quot
/ div
的原因。)通常情况下,如果您在类型签名中看到这些内容,那么概念类型错误。幸运的是,这很容易解决;由于m
和i
现在是Integer
s,您可以摆脱Integral
约束,只有Fractional
(这就是Haskell将推断的你)。
总而言之,你最终得到了新代码
crowdWrong :: Fractional a => Integer -> a
crowdWrong m = crowdWrong' m m
crowdWrong' :: Fractional a => Integer -> Integer -> a
crowdWrong' m 1 = (0.49 ^ (m-1)) * 0.51 * fromIntegral (m `choose` 1) * 0.98
crowdWrong' m i = (0.49 ^ (m-i)) * (0.51 ^ i) * fromIntegral (m `choose` i) * 0.98
+ (crowdWrong' m (i - 1))
choose :: Integer -> Integer -> Integer
choose n 0 = 1
choose 0 k = 0
choose n k = ((n-1) `choose` (k-1)) * n `div` k
(我冒昧地删除了一些冗余的括号并切换到choose
的中缀形式。)
这似乎并不完全符合您的总和:我认为您应该crowdWrong m $ m `quot` 2
,i
应该在0
而不是1
找到最低点。 crowdWrong'
中的重复很烦人。您可以将代码编写为文字sum
,从而避免手动递归。
crowd :: Fractional a => Integer -> a
crowd m = sum [ 0.49^(m-i) * 0.51^i * fromIntegral (m `choose` i) * 0.98
| i <- [0 .. m `quot` 2] ]
答案 1 :(得分:1)
您的问题是您使用的是假类型。首先,您不能同时使用b
和Fractional
类型的Integral
类型,但这是b
crowdWrong
中crowdWord'
的{{1}} {1}}。相反,您应该使用Num b
作为上下文
您的编译器抱怨的问题是,您明确表示choose
获取了两个Integer
个参数,但在crowdWrong'
中,您为其提供了类型为Num b => b
的参数。您应该将crowdWrong'
的类型签名更改为Num b => Integer -> Integer -> b
,将crowdWrong
的类型更改为Num b => Integer -> b
。