I'm trying to implement the Cantor Pairing using Haskell. The encoding of a list of ints is working fine, the decoding however is just not working due to type errors.
I tried nearly everything I could think of, but nothing would work out:
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)
As you can see, I'm using sqrt
, floor
and other things, so it's a bit messy...
OK that does look desperate. A couple points:
fromRational
, since you have no actual Rational
s here. Also, fromRational
and toFractional
are both strictly less general than their combination realToFrac
, although you don't need that either - these are all for converting between different floating point/rational types, but you have only one involved, Double
. toInteger
, which is only for converting between different Integral
types. You do want its generalization fromIntegral
which converts from an Integral
type to a general Num
. You should make a clear decision exactly which of your variables are Integer
s, and which are Double
s. Then use fromIntegral
to convert from Integer
to Double
, and floor
or another similar function to convert from Double
to Integer
, when necessary. You have several attempts there to convert between the same type (basically, all your toInteger
s.)
Given this, you can clean your type-conversion code up into (adding explicit type annotations for clarity):
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.