Using Haskell ranges: Why would mapping a floating point function across a range cause it to return an extra element? -


i know floats can lead odd behavior in ranges due imprecise nature. expect possibility of imprecise values. instance: [0.1,0.3..1] might give [0.1,0.3,0.5,0.7,0.8999999999999999] instead of [0.1,0.3,0.5,0.7,0.9]

in addition precision loss, however, element:

ghci> [0.1,0.3..1] [0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999] 

this weird, explained here. work around this, suppose:

ghci> [0.1,0.3..0.99] [0.1,0.3,0.5,0.7,0.8999999999999999] 

but that's kind of gross. maybe there's cleaner way. simple example, of course, use range [0.1,0.3..0.9] , fine.

but in more complex example, may not know (or care figure out, if i'm lazy) exact upper bound should use. so, i'll make range of integers , divide 10, right? nope:

ghci> map (/10) [1,3..10] [0.1,0.3,0.5,0.7,0.9,1.1] 

any floating point function seems cause behavior:

ghci> map (*1.0) [1,3..10] [1.0,3.0,5.0,7.0,9.0,11.0] 

whereas non-floating function doesn't:

ghci> map (*1) [1,3..10] [1,3,5,7,9] 

while seems unlikely, thought maybe lazy evaluation @ play, , tried force evaluation of range first:

ghci> let list = [1,3..10] in seq list (map (*1.0) list) [1.0,3.0,5.0,7.0,9.0,11.0] 

obviously, using literal list instead of range works fine:

ghci> map (*1.0) [1,3,5,7,9] [1.0,3.0,5.0,7.0,9.0]  ghci> let list = [1,3,5,7,9] in seq list (map (*1.0) list) [1.0,3.0,5.0,7.0,9.0] 

it isn't mapping either:

ghci> last [1,3..10] 9  ghci> 1.0 * (last [1,3..10]) 11.0 

how applying function result of range can impact actual evaluated result of range?

i answered myself writing it.

haskell uses type inference, when sees floating point function being mapped on list (or used on element of list, in example using last), going infer type of list floating point , therefore evaluate range if [1,3..10] :: [float] instead of intending, [1,3..10] :: [int]

at point, uses float rules enumerating, described in post linked in question.

the expected behavior can forced this:

ghci> map (\x -> (fromintegral x) / 10) ([1,3..10]::[int]) [0.1,0.3,0.5,0.7,0.9] 

relying on haskell's type inference, can drop ::[int] since fromintegral causes our lambda expression have correct type:

ghci> :t (\x -> (fromintegral x) / 10) (\x -> (fromintegral x) / 10)   :: (fractional a, integral a1) => a1 -> 

Comments

Popular posts from this blog

PHPMotion implementation - URL based videos (Hosted on separate location) -

javascript - Using Windows Media Player as video fallback for video tag -

c# - Unity IoC Lifetime per HttpRequest for UserStore -