Haskell主要测试

hsk*_*new 8 primes haskell short-circuiting

我是Haskell的新手,我正在尝试一下:

isPrime :: Integer->Bool
isPrime x = ([] == [y | y<-[2..floor (sqrt x)], mod x y == 0])
Run Code Online (Sandbox Code Playgroud)

我有几个问题.

  1. 为什么当我尝试加载.hs时,WinHugs说:(Floating Integer, RealFrac Integer)定义所需的实例isPrime
  2. 当解释器在右侧集合中找到一个元素时,它会立即停止或计算所有集合?我想你知道我的意思.

抱歉我的英语.

Lan*_*dei 17

1)问题是sqrt具有类型(Floating a) => a -> a,但您尝试使用Integer作为参数.因此,您必须先将Integer转换为浮动,例如通过写入sqrt (fromIntegral x)

2)我没有理由为什么==不应该是懒惰的,但是为了测试一个空集合你可以使用该null函数(这绝对是懒惰的,因为它适用于无限列表):

isPrime :: Integer->Bool
isPrime x = null [y | y<-[2..floor (sqrt (fromIntegral x))], x `mod` y == 0]
Run Code Online (Sandbox Code Playgroud)

但是为了获得更加惯用的解决方案,将问题分解为更小的子问题.首先,我们需要y*y <= x的所有元素y的列表:

takeWhile (\y ->  y*y <= x) [2..]
Run Code Online (Sandbox Code Playgroud)

那么我们只需要划分x的元素:

filter (\y ->  x `mod`y == 0) (takeWhile (\y ->  y*y <= x) [2..])
Run Code Online (Sandbox Code Playgroud)

然后我们需要检查该列表是否为空:

isPrime x = null (filter (\y ->  x `mod`y == 0) (takeWhile (\y ->  y*y <= x) [2..]))
Run Code Online (Sandbox Code Playgroud)

如果这看起来像你的lispy,用$替换一些parens

isPrime x = null $ filter (\y ->  x `mod` y == 0) $ takeWhile (\y ->  y*y <= x) [2..]
Run Code Online (Sandbox Code Playgroud)

为了更加清晰,您可以"外包"lambda:

isPrime x = null $ filter divisible $ takeWhile notTooBig [2..] where
     divisible y = x `mod`y == 0
     notTooBig y = y*y <= x
Run Code Online (Sandbox Code Playgroud)

你可以通过用$ any替换null $ filter来使它几乎"人类可读":

isPrime x = not $ any divisible $ takeWhile notTooBig [2..] where
     divisible y = x `mod`y == 0
     notTooBig y = y*y <= x
Run Code Online (Sandbox Code Playgroud)


sep*_*p2k 7

  1. 因为sqrt有类型Floating a => a -> a.这意味着输入必须是一个Floating类型,输出将是相同的类型.换句话说,x需要是一种Floating类型.但是,您声明x为类型Integer,而不是Floating类型.另外floor需要一种RealFrac类型,所以也x需要这样.

    该错误消息表明,您修复,通过使Integer一个Floating类型(通过定义一个实例Floating Integer(与同为RealFrac).

    当然,在这种情况下,这不是正确的方法.相反,你应该使用fromIntegral转换xReal(这是实例FloatingRealFrac),然后把那个给sqrt.

  2. 是.一旦==看到右操作数至少有一个元素,它就知道它不等于[]并因此返回False.

    话虽这么说,null检查列表是否为空是一种更惯用的方式[] ==.

  • 至于惯用解决方案,我建议`截断.sqrt.fromIntegral` for no.1和`all(\ y - > x \`mod \`y/= 0)[...]`. (2认同)