haskell 判断一个数是否为素数的函数,

mbjcgjjk  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(256)

`我是Haskell的新手,我正在定义一个函数,给定一个Int n,它通过搜索2〈=m〈=sqrt来判断一个数是否为素数如果m存在,那么n不是素数,如果不是,那么n是素数。我试图定义一个m在2和sqrt n之间的列表,我的想法是,如果列表是空的,那么n是素数,否则,n不是素数'

isprime' :: Int -> Bool           
isprime' n | l == [] = True
           | otherwise = False

           where 
            l = [x|x<-[2.. sqrt n], mod n x == 0]

`
但是当我运行我的代码时,sqrt n似乎出现了问题,我无法理解它。有人能解释一下我做错了什么/为了让我的代码运行需要修改什么/以及为什么会出现错误吗?

pgx2nnw8

pgx2nnw81#

运行该代码会产生以下错误

test.hs:9:28: error:
    • No instance for (Floating Int) arising from a use of ‘sqrt’
    • In the expression: sqrt n
      In the expression: [2 .. sqrt n]
      In a stmt of a list comprehension: x <- [2 .. sqrt n]
  |
9 |             l = [x|x<-[2.. sqrt n], mod n x == 0]
  |                            ^^^^^^

你说sqrt有问题是正确的,但是对于一个新的Haskell开发人员来说,其余的部分是相当不透明的。让我们检查一下sqrt的类型,看看这是否有帮助。

Prelude> :t sqrt
sqrt :: Floating a => a -> a

这里我使用ghci来交互地编写代码。:t要求前面表达式的类型。sqrt :: Floating a => a -> a行表示sqrt接受某个浮点数a,并返回相同类型的值。
类似于我们的错误消息,我们看到这个Floatingthing。这个 thing 是一个typeclass,但是为了解决这个问题,我们将把理解这些留到以后。本质上,haskell试图告诉您Int不是sqrt所期望的浮点数。我们可以通过将Int转换为带有fromIntegralFloat来修正这个问题,fromIntegral是一个将数类型转换为另一个数类型的通用函数。(参见Get sqrt from Int in Haskell

isprime' :: Int -> Bool           
isprime' n | l == [] = True
           | otherwise = False
           where         
            asFloat :: Float -- new! - tell fromIntegral we want a float
            asFloat = fromIntegral n -- new! turn n into a Float
            l = [x|x<-[2..sqrt asFloat], mod n x == 0]

这也是错误的!但它是一个新的!

test.hs:10:48: error:
    • Couldn't match expected type ‘Int’ with actual type ‘Float’
    • In the second argument of ‘mod’, namely ‘x’
      In the first argument of ‘(==)’, namely ‘mod n x’
      In the expression: mod n x == 0
   |
10 |             l = [x|x<-[2..sqrt asFloat], mod n x == 0]
   |                                                ^

这就是说x突然变成了Float,当我们变成[2..sqrt asFloat]时,我们现在已经得到了一个Float的列表([Float]),我们需要把它变回[Int],我们可以通过对平方根的结果调用floor来完成。

isprime' :: Int -> Bool           
isprime' n | l == [] = True
           | otherwise = False
           where         
            asFloat :: Float
            asFloat = fromIntegral n 
            l = [x|x<-[2..floor (sqrt asFloat)], mod n x == 0] -- new! I added floor here to change the result of sqrt from a `Float` into a `Int`

现在可以正确编译。

相关问题