哈斯克尔列表条件



我昨天已经开始学习Haskell,所以你可以认为我是一个完全的新手。

我想要一个质数列表,所以我说:

multiples max reihe = [ x | x <- [reihe*2,reihe * 3..max], x<= max ]
notPrimes max = [ truncate x | x <- concat [ multiples max reihe | reihe <- [2..(max/2)]]]
primes max = [ x | x <- [2..max] , elem x (notPrimes max) ]

第一个代码片段是一个函数,它返回不超过max的所有reihe倍数。

第二个是返回除1之外的所有非素数的函数,直到指定的最大值。

最后一个片段不起作用,我不明白为什么。如果我用任意值x评估elem x (notPrimes max),我会得到答案,但这个"过滤器"会抛出一个错误:

<interactive>:47:1: error:
* Ambiguous type variable `a0' arising from a use of `print'
prevents the constraint `(Show a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Show Ordering -- Defined in `GHC.Show'
instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
instance Show Integer -- Defined in `GHC.Show'
...plus 23 others
...plus 15 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In a stmt of an interactive GHCi command: print it

问题在于使用由/运算符引起的小数。

当函数truncate某种RealFrac类型转换为某种Integral类型时,以下等式:

notPrimes max = [ truncate x | x <- concat [ multiples max reihe | reihe <- [2..(max/2)]]

将强制参数max为分数,并将notPrimes的结果作为整数值的列表。

但是,这个等式:

primes max = [ x | x <- [2..max] , elem x (notPrimes max) ]

将迫使xmax一样是分数,像notPrime max元素一样是积分。请记住,Haskell不进行隐式类型转换。

因此,当你试图实际评估类似primes 100的东西时,你强迫Haskell解释器为每个事物分配实际类型,事情变得丑陋。

关键思想是:

  1. 不要在整数问题中使用小数,除非确实有必要
  2. 酌情使用显式类型签名

此外,正如评论中提到的,缺少一个逻辑否定(一个额外的not调用)。

可能的仅积分解决方案:

$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/  :? for help
λ> 
λ> :type (/)
(/) :: Fractional a => a -> a -> a
λ> 
λ> :type div
div :: Integral a => a -> a -> a
λ> 
λ> multiples max reihe = [ x | x <- [reihe*2,reihe * 3..max], x<= max ]
λ> notPrimes max = [ x | x <- concat [ multiples max reihe | reihe <- [2..(div max 2)]]]
λ> primes max = [ x | x <- [2..max] , not $ elem x (notPrimes max) ]
λ> 
λ> primes (100::Int)
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
λ> 

最新更新