coulomb-refined
The coulomb-refined package defines algebra typeclasses for integrating the
refined
typelevel libraries with coulomb.
Quick Start
documentation
You can browse the coulomb-refined api definitions
here.
packages
Include coulomb-refined with your Scala project:
libraryDependencies += "com.manyangled" %% "coulomb-core" % "0.9.1"
libraryDependencies += "com.manyangled" %% "coulomb-refined" % "0.9.1"
import
// fundamental coulomb types and methods
import coulomb.*
import coulomb.syntax.*
// common refined definitions
import eu.timepit.refined.*
import eu.timepit.refined.api.*
import eu.timepit.refined.numeric.*
// algebraic definitions
import algebra.instances.all.given
// algebra typeclasses for refined integrations
import coulomb.integrations.refined.all.given
// coulomb syntax for refined integrations
import coulomb.integrations.refined.syntax.*
examples
Examples in this section will use the following workaround as a replacement for refineMV until it is ported forward to Scala 3.
// a workaround for refineMV not being available in scala3
// https://github.com/fthomas/refined/issues/932
object workaround:
extension [V](v: V)
def withRP[P](using Validate[V, P]): Refined[V, P] =
refineV[P].unsafeFrom(v)
import workaround.*
The coulomb-refined package supports refined predicates that are algebraically well-behaved for applicable operations.
Primarily this means the predicates
Positive
and
NonNegative.
For example, the positive doubles are an additive semigroup and multiplicative group,
as the following code demonstrates.
The
table
below summarizes the full list of supported refined predicates and associated algebras.
import coulomb.units.si.{*, given}
import coulomb.units.us.{*, given}
val pos1 = 1d.withRP[Positive].withUnit[Meter]
// pos1: Quantity[(Double Refined Positive), Meter] = 1.0
val pos2 = 2d.withRP[Positive].withUnit[Meter]
// pos2: Quantity[(Double Refined Positive), Meter] = 2.0
val pos3 = 3d.withRP[Positive].withUnit[Second]
// pos3: Quantity[(Double Refined Positive), Second] = 3.0
// positive doubles are an additive semigroup
pos1 + pos2
// res0: Quantity[(Double Refined Positive), Meter] = 3.0
// also a multiplicative semigroup
pos1 * pos2
// res1: Quantity[(Double Refined Positive), ^[Meter, 2]] = 2.0
pos2.pow[2]
// res2: Quantity[(Double Refined Positive), ^[Meter, 2]] = 4.0
// also a multiplicative group
pos2 / pos3
// res3: Quantity[(Double Refined Positive), /[Meter, Second]] = 0.6666666666666666
pos2.pow[0]
// res4: Quantity[(Double Refined Positive), 1] = 1.0
The standard refined function for refining values with run-time checking is
refineV,
which returns an
Either.
The coulomb-refined package supplies a similar variation refinedVU.
These objects are also supported by algebras.
// This refinement succeeds, and returns a Right value
val pe1 = refineVU[Positive, Meter](1)
// pe1: Quantity[Either[String, (Int Refined Positive)], Meter] = Right(
// value = 1
// )
// This refinement fails, and returns a Left value
val pe2 = refineVU[Positive, Meter](0)
// pe2: Quantity[Either[String, (Int Refined Positive)], Meter] = Left(
// value = "Predicate failed: (0 > 0)."
// )
// positives are an additive semigroup
pe1 + pe1
// res5: Quantity[Either[String, (Int Refined Positive)], Meter] = Right(
// value = 2
// )
// algebras operating on Left values result in a Left
pe1 + pe2
// res6: Quantity[Either[String, (Int Refined Positive)], Meter] = Left(
// value = "Predicate failed: (0 > 0)."
// )
algebra support table
The following table summarizes the algebras and operations supported by this package.
Examples of Fractional value types include Double, Float,
BigDecimal,
spire Rational, etc.
Integral value types include Int, Long, BigInt, etc.
| Value Type | Predicate | Add Alg | Mult Alg | + |
* |
/ |
pow (exponent) |
|---|---|---|---|---|---|---|---|
| Fractional | Positive | semigroup | group | Y | Y | Y | Y (rational) |
| Fractional | NonNegative | semigroup | semigroup | Y | Y | N | Y (pos int) |
| Integral | Positive | semigroup | semigroup | Y | Y | N | Y (pos int) |
| Integral | NonNegative | semigroup | semigroup | Y | Y | N | Y (pos int) |
The table above also applies to Either objects returned by refineVU as discussed
in the examples section above.