haskell的组合地板和sqrt

haskell的组合地板和sqrt,haskell,sqrt,floor,Haskell,Sqrt,Floor,我只是在学习haskell(我自己,为了好玩),我遇到了困难 我的问题: 如何定义函数 flrt = (floor . sqrt) 当我在文件和编译中尝试它时,GCHi抱怨如下: AKS.hs:11:9: No instance for (RealFrac Integer) arising from a use of `floor' Possible fix: add an instance declaration for (RealFrac Integer)

我只是在学习haskell(我自己,为了好玩),我遇到了困难

我的问题:

如何定义函数

flrt = (floor . sqrt)
当我在文件和编译中尝试它时,GCHi抱怨如下:

AKS.hs:11:9:
    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 . sqrt)
    In an equation for `flrt': flrt = (floor . sqrt)

AKS.hs:11:17:
    No instance for (Floating Integer)
      arising from a use of `sqrt'
    Possible fix: add an instance declaration for (Floating Integer)
    In the second argument of `(.)', namely `sqrt'
    In the expression: (floor . sqrt)
    In an equation for `flrt': flrt = (floor . sqrt)
我不明白为什么结果函数不只是Int->Int

我刚刚完成了第二年的CS课程,并完成了一门基础PL课程。我听说过,但还不太了解类型。我试着读了几本哈斯克尔的教程,但都读不懂

我也不明白什么是单子。(我搜索到的许多其他问题都谈到了这些)

p.p.S.-我的全部资料来源

bar = \a b -> if (2^a) > b
                then (a-1)
                else bar (a+1) b
foo = bar 1

flrt :: Integer -> Integer
flrt = (floor . sqrt)

aks target = if (target < 2)
                then putStr "Not a Prime.\n\n"
                else if elem (mod target 10) [0,2,4,5,6,8]
                        then putStr "Composite\n\n"
                        else if (elem target) [a^b | a <- [3,5..(flrt target)], b <- [1.. (foo target)]]

                                then putStr "Composite\n\n"--}
                            else 
                            putStr "filler"
bar=\ab->if(2^a)>b
然后(a-1)
其他条(a+1)b
foo=bar 1
整数->整数
flrt=(floor.sqrt)
aks目标=if(目标<2)
然后putStr“不是素数。\n\n”
else如果元素(国防部目标10)[0,2,4,5,6,8]
然后putStr“Composite\n\n”

else if(elem target)[a^b | a问题在于您试图使用
Integer
作为输入。Haskell是强类型的,这意味着没有任何类型的隐式强制或转换。请查看您试图编写的函数的签名:

sqrt  :: Floating a => a -> a
floor :: (RealFrac a, Integral b) => a -> b
在GHC推断出的函数签名处:

> :t floor . sqrt
floor . sqrt :: (RealFrac b, Integral c, Floating b) => b -> c
因此,要使函数从
Integer
(没有
Floating
实例)变为
Integer
,必须首先将参数转换为
Floating
,这可以通过使用
fromIntegral
实现:

> :t floor . sqrt . fromIntegral
floor . sqrt . fromIntegral :: (Integral a, Integral c) => a -> c

正如copumpkin所说,在这里转换为浮点实际上可能不是一个好主意,因为这会导致精度损失,因此,即使使用舍入,对于足够大的整数输入,也可能产生不正确的结果

我假设您处理的所有数字至少都足够小,可以用浮点表示,例如,所有数字都小于10300

Prelude> round(sqrt.fromInteger$10^60 :: Double) ^ 2
1000000000000000039769249677312000395398304974095154031886336
Prelude>  {-   and not   -}     10^60    {-  == (10^30)^2 == (sqrt$10^60) ^ 2  -}
1000000000000000000000000000000000000000000000000000000000000
就绝对差而言,这是一个很大的差距。但相对于数字本身来说,它确实是一个相当好的近似值,因此您可以使用它作为快速确定的算法起点,以找到精确的结果。您可以使用
整数
s实现牛顿/拉斐逊(在本例中称为Heron):

flrt :: Integer -> Integer  -- flrt x ≈ √x,  with  flrt x^2 ≤ x < flrt(x+1)^2
flrt x = approx (round . (sqrt::Double->Double) . fromInteger $ x)
   where approx r
            | ctrl <= x, (r+1)^2 > x  = r
            | otherwise               = approx $ r - diff
          where ctrl = r^2
                diff = (ctrl - x) // (2*r)    -- ∂/∂x x² = 2x

         a//b = a`div`b + if (a>0)==(b>0) then 1 else 0   -- always away from 0

牛顿-拉斐逊修正中始终远离0的除法在这里是必要的,以防止陷入无限递归。

floor$sqrt
意味着
floor sqrt
-您试图将
floor
应用于函数
sqrt
。您想要的是函数组合。尝试
floor.sqrt
@Vitus:Y你本可以找到答案的!好吧,我的错;这确实行得通。但我在编译它时仍然有一个问题。请记住,你可能实际上并不想要
floor.sqrt
,而是想要
intSqrt::Integer->Integer
(或者
Natural->Natural
,真的)相反,
sqrt
会经历一个不精确的
Float
Double
,并且考虑到素性测试通常适用于非常大的数字,精度的损失最终可能会咬到你。但是,你的算法并不特别适合大的数字,所以你可能会很好:)@copumpkin:谢谢!还有嗯……最终的结果是它可以处理非常大的数字,但我想我应该从一个简单的实现开始,然后阅读一些数值分析,然后再进行一遍。数值分析中的+1=)但是你也可以解释一下
flip const“,而不是:“(10^60)==(10^30)^2=(sqrt$10^60)^2”
我不明白它是如何给出(sqrt$10^60)^2(这就是它给出的正确吗?)的。不,不是,对不起。这只是在
(10^60)
之前插入注释的愚蠢方式。
*IntegerSqrt> (flrt $ 10^60) ^ 2
1000000000000000000000000000000000000000000000000000000000000