我正在尝试创建一个基本函数来测试Haskell中整数的素数。我有一些代码可以在临时意义上工作,但在我尝试将其传递给函数时会继续收到错误消息。请注意,我使用:{
和:}
直接在GHCi中编写定义。
我们的想法是创建一个N模数列表{所有整数直到舍入的sqrt(N)},然后测试结果列表中除初始索引之外的零。以下四个功能都有效:
rndRoot :: (Floating a, Integral c, RealFrac a) => a -> c
rndRoot = round . sqrt
oneToRndRoot :: (Floating a, Integral t, RealFrac a) => a -> [t]
oneToRndRoot x = [1..rndRoot(x)]
modulo x y
| n < 0 = x
| otherwise = modulo n y
where n = x - y
mapMod x = map (modulo x)
这也有效:
mapMod 49 (oneToRndRoot 49)
然而,虽然repl接受这个定义而没有投诉......
mapModToRndRoot x = mapMod x $ oneToRndRoot x
...当我尝试使用它时,它会发出以下错误消息:
Prelude> mapModToRndRoot 39
<interactive>:475:1:
No instance for (Floating a0) arising from a use of ‘it’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Floating Double -- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
似乎工作正常的临时解决方案只是使用两个参数而不是重复相同的
mapModToRndRoot2 x y = map (modulo x) (oneToRndRoot y)
Prelude> mapModToRndRoot2 33 33
[0,1,0,1,3,3]
答案 0 :(得分:5)
检查openat
的类型给出以下内容:
libc.so
因此,要致电mapModToRndRoot
,我们需要为文字mapModToRndRoot :: (Floating a, Integral a, RealFrac a) => a -> [a]
指定一个数字类型,该文字是mapModToRndRoot 39
,39
的实例,并且RealFrac
。但是,Prelude数字类型都不能满足所有这三个约束,因此我们得到了编译错误。
另一方面,Integral
工作正常。注意下面lambda的类型:
Floating
通过使用两个文字,GHC能够为每个文字分配不同的类型,以满足类型类约束。
编辑:以下是@duplode建议的解决方案:
mapMod 49 (oneToRndRoot 49)
我的原始建议\x y -> mapMod x (oneToRndRoot y)
:: (RealFrac a, Integral b, Floating a) => b -> a -> [b]
容易受到使用浮点运算所带来的所有常见的困难。
编辑:正如@WarrickMacmillan指出的那样,rndRoot :: (Integral a) => a -> a
rndRoot = round . sqrt . fromIntegral
的签名也必须改变。以下是完整注释的整个工作程序。
fromIntegral . round . sqrt