Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

odd behaviour of Sz1 when subtracting something #114

Closed
ilcasinistareloaded opened this issue May 11, 2021 · 2 comments
Closed

odd behaviour of Sz1 when subtracting something #114

ilcasinistareloaded opened this issue May 11, 2021 · 2 comments

Comments

@ilcasinistareloaded
Copy link

ilcasinistareloaded commented May 11, 2021

Hello again. There is something odd going on here. With Int it works OK but with Sz1 there is a problem. (GHC 8.10.4; massiv 0.6). Thanks!

import Data.Massiv.Array (Sz(..), Sz1)

f  :: Sz1 -> Sz1
f   = ($) (\ x -> x - 1)

f' :: Sz1 -> Sz1
f' = ($) (+ (- 1))


ok  = f  (Sz 10) -- 9
bug = f' (Sz 10) -- 10 <-- THIS SHOULD BE 9.
@lehins
Copy link
Owner

lehins commented May 11, 2021

Hello again, and you again find some more odd behavior with regards to Num ;)

This is a very good observation. However, it is a totally explainable one: Sz cannot be negative by construction. So when you use prefix -, eg: -1 :: Sz1 it will be desugared into Sz (max 0 (fromInteger (negate 1))) == Sz 0, which is different from the infix -, eg. 5 - 1, because latter is desugared into Sz (max 0 (fromInteger 5) - max 0 (fromInteger 1))

This is not the first place in Haskell when this behavior related to how numeric literals are desugared produces surprising results. In fact you can replicate similar behavior with the Natural:

import Numeric.Natural

f  :: Natural -> Natural
f   = ($) (\ x -> x - 1)

f' :: Natural -> Natural
f' = ($) (+ (- 1))

ok  = f  10 -- 9
bug = f' 10 -- 10 <-- THIS SHOULD BE 9.

Which results in:

λ> ok
9
λ> bug
*** Exception: arithmetic underflow

We could fix this deficiency for Sz by producing an error instead of silently enforcing non-negative sizes with max, but I am leaning towards removing Num instance for Sz because this sort of behavior is unexpected and undesirable no matter how you look at it. Maybe, we should do both.

The proper workaround is to unwrap Sz and operate on Ix when doing arithmetic and then construct Sz back when size is needed.

Thank you for pointing out this deficiency.

@ilcasinistareloaded
Copy link
Author

Clear explanation, thanks! I didn't know there was a similar issue with Natural. If that is a common knowledge I think this issue can be closed with just a comment in the docs about this pitfall.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants