Skip to content

Conversation

@dmcclean
Copy link
Collaborator

Fixes #145.

This draft just outright takes the ieee754 dependency, because it seems stable, is on stackage, and only itself depends on base, so it doesn't feel like it's worth the flag dance contemplated in #111 / #95.

@dmcclean dmcclean added this to the Version 1.1 milestone Jan 27, 2016
@bjornbm
Copy link
Owner

bjornbm commented Jan 29, 2016

Sweet!

I feel we should give Patrick Perry/ieee754 some credit in Float since we are pretty much ripping of his API wholesale.

However, what do you think of instead proposing bjornbm/hs-ieee754#1 which I believe would allow us to newtype-derive IEEE?

@dmcclean
Copy link
Collaborator Author

Yup, we should definitely give him credit. And also ask permission. I'll get in touch later today. My mistake.

I originally thought we could just have an instance, which GND will let us do easily, but I found a problem with it.

-- | The smallest positive value @x@ such that @1 + x@ is representable.
epsilon :: IEEE a => Dimensionless a -- not Quantity d a
epsilon = Quantity $ F.epsilon

Perhaps if we also split epsilon from the class and defined it thus, but I don't know the performance implications, and it would be a breaking change:

epsilon :: (IEEE a, RealFloat a) => a
epsilon = (succIEEE 1) - 1

On balance I think we are better off with this style of wrapper like we have around the RealFloat stuff, but I'm open to changing my mind.

@dmcclean
Copy link
Collaborator Author

I spoke with Patrick by email and he approved the plan of crediting him in the module comments.

bjornbm added a commit that referenced this pull request Jan 29, 2016
Added AEq instance and convenience wrappers around IEEE functions
@bjornbm bjornbm merged commit 2dfb662 into bjornbm:master Jan 29, 2016
@bjornbm
Copy link
Owner

bjornbm commented Jan 29, 2016

I'm not sure I understood the problem with epsilon (other than documentation: 1 *~ siUnit + x?), but perhaps I am just being daft.

I tried with GND but got error messages on the following form which I don't quite understand:

/Users/bjorn/repos/dimensional/src/Numeric/Units/Dimensional/Internal.hs:81:29:
    Couldn't match representation of type ‘a’
                             with that of ‘Dimensional 'DQuantity d a’
      ‘a’ is a rigid type variable bound by
          the instance declaration
          at src/Numeric/Units/Dimensional/Internal.hs:81:29
    Relevant role signatures:
      type role Dimensional nominal nominal nominal
    Relevant bindings include
      infinity :: Dimensional 'DQuantity d a
        (bound at src/Numeric/Units/Dimensional/Internal.hs:81:29)
    In the expression:
        coerce (infinity :: a) :: Dimensional DQuantity d a
    In an equation for ‘infinity’:
        infinity = coerce (infinity :: a) :: Dimensional DQuantity d a
    When typechecking the code for  ‘infinity’
      in a derived instance for ‘IEEE (Dimensional 'DQuantity d a)’:
      To see the code I am typechecking, use -ddump-deriv
    In the instance declaration for ‘IEEE (Dimensional 'DQuantity d a)’

In particular:

    Couldn't match representation of type ‘a’
                             with that of ‘Dimensional 'DQuantity d a’

Why would they not match?? This type of error occurs for all methods without arguments.

@bjornbm
Copy link
Owner

bjornbm commented Jan 30, 2016

I also couldn't seem to get -ddump-deriv to work. Tried stack build --ghc-options=-ddump-deriv.

@dmcclean
Copy link
Collaborator Author

My issue with epsilon is the (1 *~ siUnit + x) bit. That makes it a totally arbitrary quantity with no interesting properties, doesn't it?

The GND bit is the role signature thing biting us again. It's impossible to convince current GHC that the role signature of Dimensional should be type role Dimensional nominal phantom representational and not the type role Dimensional nominal nominal nominal that it infers, because it doesn't allow declaring signatures for type families (well, it's a data family in this case, but not that either). It also can't look through the type synonym and see that once Dimensional DQuantity has been partially applied that the role signature of what's left is phantom representational, instead it still thinks it's nominal nominal and so it thinks it isn't allowed to derive the instance because a appears at a nominal role. See https://ghc.haskell.org/trac/ghc/ticket/8177.

@dmcclean dmcclean deleted the aeq branch January 30, 2016 16:32
@bjornbm
Copy link
Owner

bjornbm commented Jan 30, 2016

Re epsilon; isn't the same true for, e.g., succIEEE, minNormal, and so on?

On 30 jan. 2016, at 17:31, Douglas McClean notifications@github.com wrote:

My issue with epsilon is the (1 *~ siUnit + x) bit. That makes it a totally arbitrary quantity with no interesting properties, doesn't it?

The GND bit is the role signature thing biting us again. It's impossible to convince current GHC that the role signature of Dimensional should be type role Dimensional nominal phantom representational and not the type role Dimensional nominal nominal nominal that it infers, because it doesn't allow declaring signatures for type families (well, it's a data family in this case, but not that either). It also can't look through the type synonym and see that once Dimensional DQuantity has been partially applied that the role signature of what's left is phantom representational, instead it still thinks it's nominal nominal and so it thinks it isn't allowed to derive the instance because a appears at a nominal role. See https://ghc.haskell.org/trac/ghc/ticket/8177.


Reply to this email directly or view it on GitHub.

@dmcclean
Copy link
Collaborator Author

dmcclean commented Feb 2, 2016

I don't think it is the same, actually. minNormal returns the minimum quantity of a certain dimension that has a normal-form representation. Which quantity this is ends up being a property of both the representation type and the unit we chose, but it doesn't really leak the concept of units. succIEEE is similar, the next representable quantity of a certain dimension larger than a given one (and some nan/infinity magic).

I can't figure out how to document what epsilon does without mentioning the units, unless it has type IEEE a => Dimensionless a instead of IEEE a => Quantity d a, so I gave it the narrower type.

@bjornbm
Copy link
Owner

bjornbm commented Feb 3, 2016

My thinking is that the size (physically speaking) of the quantity (minNormal) or the size of the increment (succIEEE) is inherently linked to our choice of unit (i.e., SI). Similar to epsilon being linked to the SI unit.

I don’t feel strongly about this so if you do leave as it. We can always relax epsilon later if necessary/useful.

On 2016-02-02, at 19:36, Douglas McClean notifications@github.com wrote:

I don't think it is the same, actually. minNormal returns the minimum quantity of a certain dimension that has a normal-form representation. Which quantity this is ends up being a property of both the representation type and the unit we chose, but it doesn't really leak the concept of units. succIEEE is similar, the next representable quantity of a certain dimension larger than a given one (and some nan/infinity magic).

I can't figure out how to document what epsilon does without mentioning the units, unless it has type IEEE a => Dimensionless a instead of IEEE a => Quantity d a, so I gave it the narrower type.


Reply to this email directly or view it on GitHub #149 (comment).

@dmcclean
Copy link
Collaborator Author

dmcclean commented Feb 4, 2016

I know what you are saying, all those values are linked and would be different quantities if we had picked a different unit, holding the representation type constant. I'm picking nits but I'm saying that both the value and the definition of the value are linked for epsilon, or at least I can't figure out a way to reword it where it isn't.

Digression

Another angle to my objection is that I still want my fixed-point branch to go through once I clear up some details, so I've been thinking in that frame of mind.

(We wouldn't actually need or even want to adopt the following generalizations because scaled floating point quantities aren't something you really need unless you are talking about lots of yotta gram / milli liter and exceed the exponent range of a small floating point type. But I think they are illustrative of my point anyway, because they bring my objection into code instead of documentation.)

This just works, with the scale factor merrily coming along (with no runtime representation) into the answer:

-- | Return the next largest representable floating-point quantity (@Infinity@ and @NaN@ are unchanged).
succIEEE :: IEEE a => Quantity d a -> Quantity d a
succIEEE = liftQ F.succIEEE

-- | The smallest representable positive quantity whose representation is normalized.
minNormal :: IEEE a => Quantity d a
minNormal = Quantity $ F.minNormal

This doesn't work, it doesn't do what the documentation says it does:

-- | The smallest positive value @x@ such that @(1 *~ siUnit + x)@ is representable.
epsilon :: IEEE a => SQuantity s d a
epsilon = Quantity $ F.epsilon

(If it's not clear, the reason it doesn't is because 1 *~ siUnit isn't necessarily equivalent to Quantity 1 anymore. And so the previous documentation must have somehow been smuggling that equivalence in even though I can't pinpoint exactly how?)

@bjornbm
Copy link
Owner

bjornbm commented Feb 5, 2016

I see your point. But it seems The smallest positive value @x@ such that @1 + x@ is representable wouldn't hold necessarily hold or be interesting for SQuantity s DOne a either? If so should we just reexport Numeric.IEEE.epsilon, or omit it altogether?

@dmcclean
Copy link
Collaborator Author

dmcclean commented Feb 5, 2016

I think holding it at IEEE a => Dimensionless a works, because Dimensionless (like all the quantity synonyms) fixes the scale factor at 1. So you can still use it at that type. Also its original documentation in ieee754 applies at that type, because 1 + x is a sensible thing to say. So I vote for leaving it, I just think that this is a valid reason not to have an instance IEEE a => IEEE (Quantity a).

@bjornbm
Copy link
Owner

bjornbm commented Feb 8, 2016

Ah, makes sense then! But should it be _1 + x since it is formatted as code? (Or format as maths "The smallest positive value x such that 1 + x is representable.")

@dmcclean
Copy link
Collaborator Author

dmcclean commented Feb 8, 2016

I'll switch it to _1 + x which also highlights the dimensionless nature of it.

@dmcclean
Copy link
Collaborator Author

dmcclean commented Feb 8, 2016

128a827

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants