我刚开始学习Haskell.我决定为自己设定一个实现我的旧算法的目标http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.79.7006&rep=rep1&type=pdf
首先,我编写了以下代码
phi [] = [1..]
phi (p:pl) = (phi pl) `minus` (map (p*) $ phi pl)
primes x
| x < 2 = []
| otherwise = smallprimes ++ (takeWhile (<=x) $tail $ phi $ reverse smallprimes)
where smallprimes = primes $ sqrt x
minus (x:xs) (y:ys) = case (compare x y) of
LT -> x : minus xs (y:ys)
EQ -> minus xs ys
GT -> minus (x:xs) ys
minus xs _ = xs
Run Code Online (Sandbox Code Playgroud)
这个函数按预期运行,除了素数列表是浮点数!有点想法告诉我,因为sqrt的签名是
sqrt :: (Floating a) => a -> a
Run Code Online (Sandbox Code Playgroud)
Haskell编译器已经确定primes正在返回一个浮点列表.但是,当我试图告诉它时
phi :: [Integer] -> [Integer]
Run Code Online (Sandbox Code Playgroud)
这就是我想要的,编译器有一个问题:
No instance for (Floating Integer)
arising from a use of `sqrt` at ...
Run Code Online (Sandbox Code Playgroud)
那么我如何表示phi将整数列表作为输入,并且输出会产生无限的整数列表?
代码中的问题是,sqrt
需要一个浮点数并返回相同的值.您必须使用转换类型的包装器才能使其工作.(这基本上就是错误信息所说的):
smallprimes = primes . ceiling . sqrt . fromIntegral $ x
Run Code Online (Sandbox Code Playgroud)
Haskell在不同的数字类型之间没有自动转换,因为Haskell所具有的类型系统不可能.