Skip to content

Instantly share code, notes, and snippets.

@p-pavel
Last active March 29, 2020 17:35
Show Gist options
  • Save p-pavel/bfad86676e7dde026cfafab1b1b36b7c to your computer and use it in GitHub Desktop.
Save p-pavel/bfad86676e7dde026cfafab1b1b36b7c to your computer and use it in GitHub Desktop.
// Тест текущего компилятора Scala3/Dotty и освоение возможностей
// Где взять, как пользоваться VSCode в качестве IDE и
// дока по языку -- здесь: https://dotty.epfl.ch/docs/index.html
/** Основыные алгебраические структур (без законов)
*/
object AlgebraicStructures {
trait Semigroup[T] {
def op(a: T, b: T): T
}
trait CommutativeSemigroup[T] extends Semigroup[T] // Laws only
trait Monoid[T] extends Semigroup[T] {
def id: T
}
trait Group[T] extends Monoid[T] {
def inverse(a: T): T
}
trait CommutativeMonoid[T] extends Monoid[T] with CommutativeSemigroup[T]
trait AbelianGroup[T] extends Group[T] with CommutativeMonoid[T]
trait Semiring[T] {
val additive: CommutativeMonoid[T]
val multiplicative: Monoid[T]
}
trait CommutativeSemiring[T] extends Semiring[T] {
val multiplicative: CommutativeMonoid[T]
}
trait Ring[T] extends Semiring[T] {
val additive: AbelianGroup[T]
}
trait CommutativeRing[T] extends Ring[T] with CommutativeSemiring[T]
trait Field[T] extends CommutativeRing[T] {
val multiplicative: AbelianGroup[T] // excluding zero :(
}
}
/** Удобный синтаксис */
object AlgebraicSyntax {
import AlgebraicStructures._
inline def [T](a: T).negate(using r: Ring[T]): T = r.additive.inverse(a)
inline def zero[T](using r: Semiring[T]): T = r.additive.id
inline def one[T](using r: Semiring[T]): T = r.multiplicative.id
inline def [T](a: T).+(b: T)(using r: Semiring[T]): T = r.additive.op(a,b)
inline def [T](a: T).*(b: T)(using r: Semiring[T]): T = r.multiplicative.op(a,b)
inline def [T](a: T).-(b: T)(using r: Ring[T]): T = a + r.additive.inverse(b)
inline def [T](a: T).reciprocal(using r: Field[T]): T = r.multiplicative.inverse(a)
inline def [T](a: T)./(b: T)(using r: Field[T]): T = a * b.reciprocal;
}
/** Понятие действительных и комплексных чисел */
object Numbers {
import AlgebraicStructures._
type RealNumber[T] = Field[T] & Ordering[T]
final case class Complex[T] (val re: T, val im: T )(using isReal: => RealNumber[T])
/** Поле комплексных чисел */
trait ComplexField[T: RealNumber] extends Field[Complex[T]] {
type Carrier = Complex[T]
import AlgebraicSyntax._
object additive extends AbelianGroup[Carrier] {
def inverse(a: Carrier) = Complex(a.re.negate, a.im.negate)
def id: Carrier = Complex(zero,zero)
def op(a: Carrier, b: Carrier) = Complex(a.re + b.re, a.im + b.im)
}
object multiplicative extends AbelianGroup[Carrier] {
def id: Carrier = Complex(one, zero)
def op(a: Carrier, b: Carrier) = Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re)
def inverse(a: Carrier) = {
val denom = a.re * a.re + a.im * a.im
Complex(a.re / denom, (a.im / denom).negate)
}
}
}
given [T: RealNumber] as Field[Complex[T]] = new ComplexField[T] {}
}
object VectorFields {
import AlgebraicStructures._
trait VectorField[Scalar, T] extends Field[Scalar] with AbelianGroup[T] {
def scalaMul(a: Scalar, t: T): T
}
}
/** Связь между числами и типами, реализующими Numeric и Fractional (включая встроенные) */
object NumericStructures {
import AlgebraicStructures._
import Numbers._
trait AdditiveAbelianGroupOnNumeric[T] (using n: Numeric[T]) extends AbelianGroup[T] {
def inverse(a: T): T = n.negate(a)
def id: T = n.fromInt(0)
def op(a: T, b: T): T = n.plus(a,b)
}
trait MultiplicativeCommutativeMonoidOnNumeric[T] (using n: Numeric[T]) extends CommutativeMonoid[T] {
def id: T = n.fromInt(1)
def op(a: T, b: T): T = n.times(a,b)
}
class MultiplicativeAbelianGroupOnFractional[T] (using f: Fractional[T])
extends MultiplicativeCommutativeMonoidOnNumeric[T] with AbelianGroup[T]
{
def inverse(a: T) = f.div(f.one,a)
}
trait NumericCommutativeRing[T: Numeric] extends CommutativeRing[T]{
val additive = new AdditiveAbelianGroupOnNumeric[T] {}
val multiplicative = new MultiplicativeCommutativeMonoidOnNumeric[T] {}
}
trait FractionalField[T: Fractional] extends Field[T]{
val additive = new AdditiveAbelianGroupOnNumeric[T] {}
val multiplicative = new MultiplicativeAbelianGroupOnFractional[T]
}
trait FractionalOrdering[T: Fractional] extends Ordering[T]{
private val default: Ordering[T] = summon
def compare(a: T, b: T): Int = default.compare(a,b)
}
// Все Numeric образуют коммутативное кольцо
given [T: Numeric] as CommutativeRing[T] = new NumericCommutativeRing[T] {}
// Все Fractional образуют поле
given [T: Fractional] as RealNumber[T] = new FractionalField[T] with FractionalOrdering[T] {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment