我尝试使用Haskell实现Cantor配对。一个int列表的编码工作正常,但是由于类型错误,解码只是不起作用。
我尝试了几乎所有我能想到的东西,但没有任何结果可以解决:
cantorDecode :: Integer -> [Integer] -> [Integer]
cantorDecode e zs
| length zs == 0 = cantorDecode y [x,y]
| head zs == 0 = map toInteger $ tail zs
| otherwise = cantorDecode y ((head zs)-1 : (tail zs) ++ [x,y])
where
a = fromRational e
w = floor ((s-1.0)/2.0)
s = fromIntegral $ sqrt(8.0*e+1.0) :: Double
t = fromRational $ (w^2+w)/2.0
y = toInteger $ e - (toInteger $ floor t)
x = toInteger $ (toInteger w) - (toInteger y)
正如您所看到的,我使用的是sqrt
,floor
等其他内容,所以它有点混乱......
答案 0 :(得分:4)
确实看起来很绝望。几点:
fromRational
,因为你在这里没有实际的Rational
。此外,fromRational
和toFractional
都严格不如组合realToFrac
,尽管您也不需要 - 这些都是为了在不同之间进行转换浮点/有理类型,但只有一个涉及Double
。toInteger
,这仅适用于在不同Integral
类型之间进行转换。您执行希望其概括fromIntegral
从Integral
类型转换为通用Num
。您应该明确确定哪些变量是Integer
,哪些是Double
。然后,在必要时,使用fromIntegral
从Integer
转换为Double
和floor
或其他类似函数,以便从Double
转换为Integer
。你有几次尝试在相同的类型之间进行转换(基本上,所有toInteger
s。)
鉴于此,您可以将类型转换代码清理为(为了清晰起见,添加显式类型注释):
cantorDecode :: Integer -> [Integer] -> [Integer]
cantorDecode e zs
| length zs == 0 = cantorDecode y [x,y]
| head zs == 0 = tail zs
| otherwise = cantorDecode y ((head zs)-1 : (tail zs) ++ [x,y])
where
w = floor ((s-1.0)/2.0) :: Integer
w' = fromIntegral w :: Double
s = sqrt(8.0*fromIntegral e+1.0) :: Double
t = (w'^2+w')/2.0 :: Double
y = e - floor t :: Integer
x = w - y :: Integer