Fab*_*art 1 haskell types ghci
我想实现这笔钱.我遇到了关于类型签名的问题.

这就是它在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
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
我不知道如何解决这个问题,我想这会更容易.
编辑:
所以现在我有这个:
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
Run Code Online (Sandbox Code Playgroud)
但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.
Run Code Online (Sandbox Code Playgroud)
您的代码基本上是正确的,但您为各个部分请求的类型不匹配.
choose必须采取并返回Integers.这本身就可以,但......
crowdWrong'必须能够采取和返回任何类型b的a Fractional和a Integral. Integer只是一种具体类型(并且不是Fractional引导的实例).这就是你得到的错误:~Haskell如何拼写类型相等,所以"无法推断(b ~ Integer)"意味着b≠ Integer.请注意,这与Java和其他OO语言不同; 一个类型签名,例如crowdWrong' :: (Fractional b, Integral b) => b -> b -> b意味着crowdWrong'必须能够接受和返回任何这样的b,不是一些这样的b.(它被称为参数多态,它就像泛型/模板.)
这个错误让你咬了两次.第一个问题是,choose预计Integer参数,但你通过它m和i,这是任意类型的b.这里最简单的解决方法就是make m和i Integers,无论如何看起来(看方程式)是正确的.您使用的唯一其他地方,m并且i作为指数(^),具有类型(^) :: (Integral b, Num a) => a -> b -> a.换句话说,(^)左侧和右侧不需要具有相同的类型.
第二个问题是choose返回Integer结果,但是你将它乘以小数.你可以通过使用来解决这个问题fromInteger :: Num a => Integer -> a,它允许你构建任何类型的Number Integer.因此choose m 1,您可以编写fromInteger (choose m 1)(或者,更好看fromInteger (m `choose` 1);反引号允许您编写任何函数中缀).这甚至会编译!然而…
没有类型都是Fractional和Integral,因此您将无法调用这些函数.该Fractional型类是有理数状的东西,而Integral型类是整数状的东西.(这就是为什么Fractional有(/),并且Integral有quot/ div.)通常,如果您在类型签名中看到这些组合,则会出现概念类型错误.幸运的是,这很容易解决; 因为m和i现在Integer公司,您可以摆脱的Integral约束,只是有Fractional(这是什么哈斯克尔会推断出你).
所有人都说,你最终得到了新的代码
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
Run Code Online (Sandbox Code Playgroud)
(我冒昧地删除了一些冗余的括号并切换到中缀形式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] ]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
161 次 |
| 最近记录: |