Skip to content

Commit

Permalink
Add total, product and mean for iterable numerics (#199)
Browse files Browse the repository at this point in the history
* Add `total`, `product` and `mean` for iterable numerics

* Make `mean` and `product` work better; fix compile error
  • Loading branch information
propensive authored Mar 3, 2025
1 parent 473f930 commit 69456f6
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 3 deletions.
3 changes: 2 additions & 1 deletion lib/quantitative/src/core/quantitative.Quantitative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ object Quantitative extends Quantitative2:
object Quantity:
erased given underlying: [UnitsType <: Measure] => Underlying[Quantity[UnitsType], Double] = !!
erased given [UnitsType <: Measure]: CanEqual[Quantity[UnitsType], Quantity[UnitsType]] = !!
given [UnitsType <: Measure] => Quantity[UnitsType] is Zeroic = () => Quantity(0.0)
given numeric: [UnitsType <: Measure] => Numeric[Quantity[UnitsType]] = summon[Numeric[Double]]

given genericDuration: Quantity[Seconds[1]] is GenericDuration =
quantity => (quantity*1000.0).toLong

given numeric: [UnitsType <: Measure] => Numeric[Quantity[UnitsType]] = summon[Numeric[Double]]

given specificDuration: Quantity[Seconds[1]] is SpecificDuration =
long => Quantity(long/1000.0)
Expand Down
21 changes: 21 additions & 0 deletions lib/rudiments/src/core/rudiments-core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import denominative.*
import fulminate.*
import prepositional.*
import proscenium.*
import symbolism.*
import vacuous.*

def fixpoint[ValueType](initial: ValueType)
Expand Down Expand Up @@ -127,6 +128,26 @@ extension [ValueType](iterator: Iterator[ValueType])
inline def all(predicate: ValueType => Boolean): Boolean = iterator.forall(predicate)

extension [ValueType](iterable: Iterable[ValueType])
inline def total(using zeroic: ValueType is Zeroic): ValueType =
inline compiletime.summonInline[ValueType is Addable by ValueType] match
case addable: (ValueType is Addable by ValueType into ValueType) =>
iterable.foldLeft(zeroic.zero)(addable.add)

case _ =>
compiletime.error("No suitable Addable instance found")

inline def mean(using zeroic: ValueType is Zeroic, divisible: ValueType is Divisible by Int)
: divisible.Result =
iterable.total/iterable.size

inline def product(using unital: ValueType is Unital): ValueType =
inline compiletime.summonInline[ValueType is Multiplicable by ValueType] match
case multiplicable: (ValueType is Multiplicable by ValueType into ValueType) =>
iterable.foldLeft(unital.one)(multiplicable.multiply)

case _ =>
compiletime.error("No suitable Multiplicable instance found")

transparent inline def each(lambda: (ordinal: Ordinal) ?=> ValueType => Unit): Unit =
var ordinal: Ordinal = Prim
iterable.iterator.foreach: value =>
Expand Down
2 changes: 1 addition & 1 deletion lib/rudiments/src/core/soundness+rudiments-core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export rudiments .
triple, is, matchable, give, pipe, fuse, tap, also, Counter, loop, Loop, &, tuple, to,
WorkingDirectoryError, HomeDirectoryError, WorkingDirectory, HomeDirectory, workingDirectory,
homeDirectory, prim, sec, ter, unwind, at, Indexable, yet, Bijection, bijection, segment,
Segmentable, Digit, temporaryDirectory }
Segmentable, Digit, temporaryDirectory, total, product, mean }

package workingDirectories:
export rudiments.workingDirectories.{systemProperty, default}
Expand Down
4 changes: 3 additions & 1 deletion lib/symbolism/src/core/soundness+symbolism-core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@
*/
package soundness

export symbolism.{Addable, Subtractable, Multiplicable, Divisible, Negatable, Rootable, sqrt, cbrt}
export symbolism .
{ Addable, Subtractable, Multiplicable, Divisible, Negatable, Rootable, sqrt, cbrt, Zeroic,
Unital }
46 changes: 46 additions & 0 deletions lib/symbolism/src/core/symbolism.Unital.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ ╭───╮ ┃
┃ │ │ ┃
┃ │ │ ┃
┃ ╭───────╮╭─────────╮╭───╮ ╭───╮╭───╮╌────╮╭────╌┤ │╭───╮╌────╮╭────────╮╭───────╮╭───────╮ ┃
┃ │ ╭───╯│ ╭─╮ ││ │ │ ││ ╭─╮ ││ ╭─╮ ││ ╭─╮ ││ ╭─╮ ││ ╭───╯│ ╭───╯ ┃
┃ │ ╰───╮│ │ │ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ ╰─╯ ││ ╰───╮│ ╰───╮ ┃
┃ ╰───╮ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ ╭────╯╰───╮ │╰───╮ │ ┃
┃ ╭───╯ ││ ╰─╯ ││ ╰─╯ ││ │ │ ││ ╰─╯ ││ │ │ ││ ╰────╮╭───╯ │╭───╯ │ ┃
┃ ╰───────╯╰─────────╯╰────╌╰───╯╰───╯ ╰───╯╰────╌╰───╯╰───╯ ╰───╯╰────────╯╰───────╯╰───────╯ ┃
┃ ┃
┃ Soundness, version 0.27.0. ┃
┃ © Copyright 2021-25 Jon Pretty, Propensive OÜ. ┃
┃ ┃
┃ The primary distribution site is: ┃
┃ ┃
┃ https://soundness.dev/ ┃
┃ ┃
┃ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file ┃
┃ except in compliance with the License. You may obtain a copy of the License at ┃
┃ ┃
┃ https://www.apache.org/licenses/LICENSE-2.0 ┃
┃ ┃
┃ Unless required by applicable law or agreed to in writing, software distributed under the ┃
┃ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, ┃
┃ either express or implied. See the License for the specific language governing permissions ┃
┃ and limitations under the License. ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
*/
package symbolism

object Unital:
given Long is Unital = () => 1L
given Int is Unital = () => 1
given Short is Unital = () => 1.toShort
given Byte is Unital = () => 1.toByte
given Double is Unital = () => 1.0
given Float is Unital = () => 1.0f

trait Unital:
type Self
protected def makeOne(): Self
def one: Self = makeOne()
47 changes: 47 additions & 0 deletions lib/symbolism/src/core/symbolism.Zeroic.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ ╭───╮ ┃
┃ │ │ ┃
┃ │ │ ┃
┃ ╭───────╮╭─────────╮╭───╮ ╭───╮╭───╮╌────╮╭────╌┤ │╭───╮╌────╮╭────────╮╭───────╮╭───────╮ ┃
┃ │ ╭───╯│ ╭─╮ ││ │ │ ││ ╭─╮ ││ ╭─╮ ││ ╭─╮ ││ ╭─╮ ││ ╭───╯│ ╭───╯ ┃
┃ │ ╰───╮│ │ │ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ ╰─╯ ││ ╰───╮│ ╰───╮ ┃
┃ ╰───╮ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ ╭────╯╰───╮ │╰───╮ │ ┃
┃ ╭───╯ ││ ╰─╯ ││ ╰─╯ ││ │ │ ││ ╰─╯ ││ │ │ ││ ╰────╮╭───╯ │╭───╯ │ ┃
┃ ╰───────╯╰─────────╯╰────╌╰───╯╰───╯ ╰───╯╰────╌╰───╯╰───╯ ╰───╯╰────────╯╰───────╯╰───────╯ ┃
┃ ┃
┃ Soundness, version 0.27.0. ┃
┃ © Copyright 2021-25 Jon Pretty, Propensive OÜ. ┃
┃ ┃
┃ The primary distribution site is: ┃
┃ ┃
┃ https://soundness.dev/ ┃
┃ ┃
┃ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file ┃
┃ except in compliance with the License. You may obtain a copy of the License at ┃
┃ ┃
┃ https://www.apache.org/licenses/LICENSE-2.0 ┃
┃ ┃
┃ Unless required by applicable law or agreed to in writing, software distributed under the ┃
┃ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, ┃
┃ either express or implied. See the License for the specific language governing permissions ┃
┃ and limitations under the License. ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
*/
package symbolism

object Zeroic:
given Long is Zeroic = () => 0L
given Int is Zeroic = () => 0
given Short is Zeroic = () => 0.toShort
given Byte is Zeroic = () => 0.toByte
given Double is Zeroic = () => 0.0
given Float is Zeroic = () => 0.0f
given String is Zeroic = () => ""

trait Zeroic:
type Self
protected def makeZero(): Self
def zero: Self = makeZero()
32 changes: 32 additions & 0 deletions lib/telekinesis/src/core/telekinesis.Parameter.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
/*
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ ╭───╮ ┃
┃ │ │ ┃
┃ │ │ ┃
┃ ╭───────╮╭─────────╮╭───╮ ╭───╮╭───╮╌────╮╭────╌┤ │╭───╮╌────╮╭────────╮╭───────╮╭───────╮ ┃
┃ │ ╭───╯│ ╭─╮ ││ │ │ ││ ╭─╮ ││ ╭─╮ ││ ╭─╮ ││ ╭─╮ ││ ╭───╯│ ╭───╯ ┃
┃ │ ╰───╮│ │ │ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ ╰─╯ ││ ╰───╮│ ╰───╮ ┃
┃ ╰───╮ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ │ │ ││ ╭────╯╰───╮ │╰───╮ │ ┃
┃ ╭───╯ ││ ╰─╯ ││ ╰─╯ ││ │ │ ││ ╰─╯ ││ │ │ ││ ╰────╮╭───╯ │╭───╯ │ ┃
┃ ╰───────╯╰─────────╯╰────╌╰───╯╰───╯ ╰───╯╰────╌╰───╯╰───╯ ╰───╯╰────────╯╰───────╯╰───────╯ ┃
┃ ┃
┃ Soundness, version 0.27.0. ┃
┃ © Copyright 2021-25 Jon Pretty, Propensive OÜ. ┃
┃ ┃
┃ The primary distribution site is: ┃
┃ ┃
┃ https://soundness.dev/ ┃
┃ ┃
┃ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file ┃
┃ except in compliance with the License. You may obtain a copy of the License at ┃
┃ ┃
┃ https://www.apache.org/licenses/LICENSE-2.0 ┃
┃ ┃
┃ Unless required by applicable law or agreed to in writing, software distributed under the ┃
┃ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, ┃
┃ either express or implied. See the License for the specific language governing permissions ┃
┃ and limitations under the License. ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
*/
package telekinesis

import anticipation.*
Expand Down

0 comments on commit 69456f6

Please sign in to comment.