gpt4 book ai didi

haskell - 计算整数 `log` 的函数

转载 作者:行者123 更新时间:2023-12-01 23:01:46 25 4
gpt4 key购买 nike

我写了以下函数。

f :: Integer -> Integer
f x = if (odd x) then 0 else (floor . logBase 2) x

但是会出现以下编译时错误:

F.hs:2:31: No instance for (RealFrac Integer) arising from a use of floor'
Possible fix: add an instance declaration for (RealFrac Integer)
In the first argument of
(.)', namely `floor' In the expression: floor . logBase 2 In the expression: (floor . logBase 2) x

F.hs:2:39: No instance for (Floating Integer) arising from a use of logBase'
Possible fix: add an instance declaration for (Floating Integer)
In the second argument of
(.)', namely `logBase 2' In the expression: floor . logBase 2 In the expression: (floor . logBase 2) x Failed, modules loaded: none.



如何正确编写上述函数?

最佳答案

这会有点长,因为我不仅想为您提供有效的代码,还想深入解释这个问题,以便您更好地理解 GHC 的类型错误。

正如已经简要回答的那样(并且类型错误尽力告诉你,虽然它肯定不够清楚),以便使用 logBase x y ,两个参数xy必须都是“浮点”类型类的实例。

特别是,logBaseFloating 的一种方法类型类(来自 Prelude's documentation ):

class Fractional a => Floating a where Source
logBase :: a -> a -> a

我们还发现,同样来自 Prelude:
class (Real a, Fractional a) => RealFrac a where Source
floor :: Integral b => a -> b

也就是说,为了使用函数 (floor . logBase) ,我们需要两个参数 Fractional (因为 logBase 需要这个)和 Real (因为 floor 两者都需要)。这两者的合并定义为 RealFrac ,而这正是 GHC 提示您未能提供它的原因(在您的函数的类型声明中)。

它为什么提示?从 Prelude 我们发现以下 instance RealFrac 的声明.请注意,“ RealFrac Integer”缺失:
RealFrac Double  
RealFrac Float
RealFrac CDouble
RealFrac CFloat
Integral a => RealFrac (Ratio a)
HasResolution a => RealFrac (Fixed a)

Haskell 的工作方式是,如果你给它一个整数文字(没有小数点的连续数字),它将假定它属于 Integral typeclass(并会尝试确定是否将其设为 IntegerInt 隐式),但它会 从不将整数文字隐式提升为 Fractional 之一类(包括 RealFrac )。由于没有“ RealFrac Integer”行,这意味着你不能指望 Haskell 编译你的代码。

你告诉 Haskell 你会给它 Integral通过您的显式类型声明实例(这是为什么这些通常是一个好主意的原因之一 - Haskell 会悄悄地接受您的函数声明,否则只会在使用它的客户端函数中引发编译错误):
f :: Integer -> Integer

解决方案是通过使用以下函数来提升您的整数(将 Integral s 转换为任何兼容的 Num ber 类型):
fromIntegral :: (Integral a, Num b) => a -> b
Floor执行相反方向的转换(从 FractionalIntegral ),如其类型所示。

总之你需要简单地说
f :: Integer -> Integer
f x = if (odd x) then 0 else (floor . logBase 2.0 . fromIntegral) x

注意 fromIntegral调用以使参数的类型与编译器所期望的兼容,以及 2.0 的使用( Fractional 文字)作为基础。

关于haskell - 计算整数 `log` 的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26416323/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com