-
Notifications
You must be signed in to change notification settings - Fork 23
add implicitly chain for angle conversion factors #52
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
base: master
Are you sure you want to change the base?
Conversation
Codecov Report
@@ Coverage Diff @@
## master #52 +/- ##
==========================================
- Coverage 85.82% 85.24% -0.59%
==========================================
Files 10 10
Lines 254 244 -10
==========================================
- Hits 218 208 -10
Misses 36 36
Continue to review full report at Codecov.
|
src/main/scala/libra/ops/base.scala
Outdated
| } | ||
|
|
||
| object ConversionFactor { | ||
| implicit def inductiveAngelConversionFactor[A, From <: UnitOfMeasure[Angle], To <: UnitOfMeasure[Angle], Next <: UnitOfMeasure[Angle]]( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this part be generic on any dimension D instead of Angle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i tried but i didn't work (diverging implicit expansion for type libra.ops.base.ConversionFactor), therefor i used Angle. I will try one more time to make it more generic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's ok, there's no need if you already tried! I'll take a better look at it later this week. I've debugged a fair few implicit resolution errors by now, so may have more luck.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so i'm waiting for your solution and i hope that i'll be able to understand them :)
| implicit def inductiveAngelConversionFactor[A, From <: UnitOfMeasure[Angle], To <: UnitOfMeasure[Angle], Next <: UnitOfMeasure[Angle]]( | ||
| implicit multiplicativeSemigroup: MultiplicativeSemigroup[A], | ||
| fromConversion: ConversionFactor[A, Angle, From, Next], | ||
| toConversion: Lazy[ConversionFactor[A, Angle, Next, To]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/main/scala/libra/ops/base.scala
Outdated
| } | ||
|
|
||
| object ConversionFactor { | ||
| implicit def inductiveAngelConversionFactor[A, From <: UnitOfMeasure[Angle], To <: UnitOfMeasure[Angle], Next <: UnitOfMeasure[Angle]]( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in 'Angel' here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
|
Thanks @ldrygala this looks awesome! It removes the otherwise exponential boilerplate. Sorry for not getting round to this earlier - I had a nasty cold and couldn't code for a few days. Would it be possible to make it even more generic in dimension? |
|
@zainab-ali i removed unused compose function on |
|
@ldrygala I'd like to sort out the implicit resolution issues for the general case. I don't think we're too far off a solution for this. I've been investigating why there are implicit resolution issues with general dimensions, other than What we have is a graph of potential conversions, and we'd like the compiler to pick out a specific path. However, even if the derivation works, the approach isn't ideal. This is mainly because:
@milessabin suggested the interesting alternative of providing evidence in the form of a // This can only be created with appropriate conversions from each node
implicit val conversionPath : ConversionPath[Degree :: ArcMinute :: ArcSecond :: HNil] = mkConversionPath
Deriving conversion factors would then be a matter of finding two nodes in the path and traversing all the nodes in between. This would pose a problem in cases where we wanted to define different units for the same base dimensions in different packages. implicit val conversionPathMetric : ConversionPath[Second :: Millisecond :: _ :: HNil] = mkConversionPath
implicit val conversionPathDay : ConversionPath[Second :: Hour :: Day :: HNil] = mkConversionPathAnd then somehow relate the two using a lower priority implicit. This would be a bit more effort, but would provide better messages in the long run. I'll experiment with this over the next few days, and see if I can come to a solution on it. |
|
@zainab-ali very interesting idea with conversionPath represented as HList. Is there anything I can get involved with this PR ? |
|
Would you like to have a go at it? It involves some fairly heavy induction, which is not everyone's cup of tea, believe me. The steps I'm envisaging are as follows:
Creating the path is fairly straightforward: package libra
package ops
import base.ConversionFactor
import shapeless._
import shapeless.ops.hlist._
trait ConversionPath[A, D, H <: HList] {
type Out <: HList
val path: Out
}
object ConversionPath {
type Aux[A, D, H <: HList, Out0 <: HList] = ConversionPath[A, D, H] { type Out = Out0 }
implicit def conversionPathBase[A, D, F <: UnitOfMeasure[D], T <: UnitOfMeasure[D]](
implicit ev: ConversionFactor[A, D, F, T]
): ConversionPath.Aux[A, D, F :: T :: HNil, ConversionFactor[A, D, F, T] :: HNil] =
new ConversionPath[A, D, F :: T :: HNil] {
type Out = ConversionFactor[A, D, F, T] :: HNil
val path = ev :: HNil
}
implicit def conversionPathRecurse[A, D, F <: UnitOfMeasure[D], T <: UnitOfMeasure[D],
Tail <: HList, OutTail <: HList](
implicit ev: ConversionPath.Aux[A, D, T :: Tail, OutTail],
ev1: ConversionFactor[A, D, F, T]
): ConversionPath.Aux[A, D, F :: T :: Tail, ConversionFactor[A, D, F, T] :: OutTail] =
new ConversionPath[A, D, F :: T :: Tail] {
type Out = ConversionFactor[A, D, F, T] :: OutTail
val path = ev1 :: ev.path
}
}
Step 2 is more challenging. Let me know if you'd like to give it a try. |
|
i thought that maybe there will be some easy thing to do, but it looks very hard, so therefore i can only wish you good luck. |
|
I've finally finished the package refactor! I'll be able to work on this over the weekend. |
add inductive implicit for chaining angle conversion factors, as referenced in #50