2

i want to implement a function in list comprehension. It should deletes the integers in a list of numbers.

And i have a question about it.

delete xs = [ys|ys<-xs, ys /=fromInteger (round ys) ]

xxx.hs> delete [1,2,3.0,4.5,6.7]
        [4.5,6.7]

is that means 3.0 is counted as integer instead of float?

And another question:

delete xs = [ys|ys<-xs, ys ==fromInteger (round ys) ]

this time i want it to return integers from a list of numbers.

xxx.hs> delete [1,2,3.0,4.5,6.7]
       [1.0,2.0,3.0]

since i did not give the number 1 and 2 in decimal form, why it returns the numbers in decimal?

Thanks for helping me.

John
  • 135
  • 6

1 Answers1

2

I want to implement a function in list comprehension. It should deletes the integers in a list of numbers.

In a list all elements have the same type. So in a list [1.2, 3, 4.5], the 3 is also a value of a type that is a member of the Floating typeclass.

Since i did not give the number 1 and 2 in decimal form, why it returns the numbers in decimal?

Because all the elements are of the same type. GHC will default to Double by the type defaulting rules.

Your filter does not specify that elements should be of an Integral type. This would also be non-sensical since types are resolved at compile time, not at runtime. It simply checks that ys is the same if you fromInteger (round ys). Since round 3.0 == 3, and fromInteger 3 == 3.0 in this case, it thus filters out elements with a fractional part. 1.0 and 2.0 have no fractional part.

The filtering is however not safe, for larger numbers, the mantisse can not represent every integer exactly, and thus this means that some values will be filtered retained when these are not integeral numbers. For more information, see is floating point math broken.

amalloy
  • 89,153
  • 8
  • 140
  • 205
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • ok,i got it.Since >fromInteger 9.0 returns an error instead of False, is there any function, without importing a module, that returns False when >function 9.0 ? – John Oct 12 '20 at 14:12
  • @JohnTang: no, since the exact literal that resulted in a value in not retained. `5.0` and `5` can be both `Double`s and these are the *same* `Double`. – Willem Van Onsem Oct 12 '20 at 14:13
  • `isInteger x = fromIntegral (round x) == x` doesn’t have precision issues that I can see…if a number doesn’t have enough precision to represent a fractional part, then it simply doesn’t *have* a fractional part (e.g. `2^23 + 0.5 :: Float` = `2^23` ≠ `2^23 + 1`). `round`, which uses round-to-even, won’t change that either way. That said, floats are subtle, so with the “no import” constraint I think it’s clearer to use `properFraction`: `isInteger x = let (_int, frac) = properFraction x in frac == 0.0`; or else arbitrary precision `Data.Ratio`: `isInteger x = denominator (toRational x) == 1`. – Jon Purdy Oct 13 '20 at 21:50