Haskell - 从泛型到整数|使用'floor'时没有(RealFrac Integer)的实例

时间:2018-03-03 13:45:33

标签: haskell typeclass

我正在学习哈斯克尔。

我试图解决你给出一个数字(n)的问题,你必须找到一对(m,k),其中m ^ k将使得完美的力量。

  如果存在自然数m,则

n是完美的幂。 1,和k> 1   这样m ^ k = n。

这是我到目前为止所提出的

sample 2

它有效。 但正如您所看到的,使用非常通用的类型。我想要的是它与

一起使用
module Test where

isPerfectPowerOf :: (Floating p, Enum p, RealFrac p) => p -> Maybe [(p, p)]
isPerfectPowerOf i
        | null perfectList = Nothing
        | otherwise = Just perfectList
        where perfectList = filter (\(x, _) -> floor x == x) [(logBase x i, x) | x <- [2 .. (i - 1)]]

因此,出于调试目的,我将此签名放在代码上,这给了我这些错误

isPerfectPowerOf :: Integer -> Maybe [(Integer, Integer)]

因此,如果我没有完全脱离标记,我将需要以某种方式对地板和logBase的输入进行正确的输入。

  

severity: 'Error' message: ' • No instance for (RealFrac Integer) arising from a use of ‘floor’ • In the first argument of ‘(==)’, namely ‘floor x’ In the expression: floor x == x In the first argument of ‘filter’, namely ‘(\ (x, _) -> floor x == x)’ severity: 'Error' message: ' • No instance for (Floating Integer) arising from a use of ‘logBase’ • In the expression: logBase x i In the expression: (logBase x i, x) In the second argument of ‘filter’, namely ‘[(logBase x i, x) | x <- [2 .. (i - 1)]]’

     

floor :: (RealFrac a, Integral b) => a -> b

我应该怎么做呢? 或者如果不是问题可能是什么?

1 个答案:

答案 0 :(得分:0)

所以你试过了:

perfectList :: Integer -> [(Integer, Integer)]
perfectList i = filter (\(x, _) -> floor x == x) [(logBase x i, x) | x <- [2 .. (i - 1)]]

(为了简洁起见,我将在此处理perfectList。但请注意,MaybeisPerfectPowerOf的转换可能是多余的,因为Maybe结果的虚无等同于列表的空虚。)

这会导致您引用的两种类型错误。第一个产生的原因是floor的参数必须是某种RealFrac类型,而Integral不是其中之一。类似地,出现第二个错误是因为logBase接受并返回某些Floating类型的值(因此您不仅需要将参数转换为浮点数,还需要将结果转换回Integer })。执行这些调整会导致:

perfectList :: Integer -> [(Integer, Integer)]
perfectList i = fmap (\(k, x) -> (floor k, x))
    . filter (\(k, _) -> fromIntegral (floor k) == k)
    $ [(logBase (fromIntegral x) (fromIntegral i), x) | x <- [2 .. (i - 1)]]

(请注意,为了清楚起见,我已重命名了您的日志变量;您可能还想交换成对中元素的顺序。)

由于您已经使用了列表推导,因此更容易将fmapfilter转移到其中:

perfectList :: Integer -> [(Integer, Integer)]
perfectList i = [(k', x) | x <- [2 .. (i - 1)]
    , let k = logBase (fromIntegral x) (fromIntegral i), let k' = floor k
    , fromIntegral k' == k
    ]

最后一点,使用floor检查浮点数是否真的&#34;真的&#34;圆数不完全可靠:

GHCi> fromIntegral (floor (logBase 2 (2**29))) == logBase 2 (2**29)
False

就是这样,最终更健全的方法是切换到一种算法,该算法在整个过程中使用整数算法找到完美的幂,从而完全避免浮点。 (虽然我怀疑你自己想要实现这一点,但对于现成的解决方案,请检查Math.NumberTheory.Powers module from the arithmoi package。)