Home

Awesome

singleton-ops

GitHub Workflow Status codecov Join the chat at https://gitter.im/fthomas/singleton-ops Scaladex Scala.js

This library provides type-level operations for Typelevel Scala with SIP-23.

Simple example:

import singleton.ops._

class MyVec[L] {
  def doubleSize = new MyVec[2 * L]
  def nSize[N] = new MyVec[N * L]
  def getLength(implicit length : SafeInt[L]) : Int = length
}
object MyVec {
  implicit def apply[L](implicit check : Require[L > 0]) : MyVec[L] = new MyVec[L]()
}
val myVec : MyVec[10] = MyVec[4 + 1].doubleSize
val myBadVec = MyVec[-1] //fails compilation, as required

Using singleton-ops

The latest version of the library is 0.5.0, which is available for Scala versions 2.11.12, 2.12.8, and 2.13.1.

If you're using sbt, add the following to your build:

libraryDependencies ++= Seq(
  "eu.timepit" %% "singleton-ops" % "0.5.0"
)

If you're using scala.js use %%% instead

libraryDependencies ++= Seq(
  "eu.timepit" %%% "singleton-ops" % "0.5.0"
)

Be sure to follow Typelevel Scala instructions, to be able to use literal types in your code.


Supported types:

Supported arithmetic operations:

Supported relational operations:

Supported logical operations:

Supported explicit conversion operations:

Supported string operations:

Supported constraints operations:

Supported control operations:

Supported Aux Pattern interface:

Examples

import singleton.ops._
def demo[L <: XInt](implicit p : L*L + L) : p.Out = p.value
val b : 30 = demo[5]
import singleton.ops._
def demoLong[L1 <: XLong, L2 <: XLong](implicit p : Min[L1*L1, L2+L2]) : p.Out = p.value
val bLong1 : 1L = demoLong[1L, 5L]
val bLong2 : 6L = demoLong[3L, 3L]
import singleton.ops._
def demoDouble[L1 <: XDouble, L2 <: XDouble](implicit p : L1 / L2 + 1.0) : p.Out = p.value
val bDouble : 1.2 = demoDouble[1.0, 5.0]
import singleton.ops._
def demoSumLongInt[L1 <: XLong, L2 <: XInt](implicit p : L1 + L2) : p.Out = p.value
val bSumLongInt : 16L = demoSumLongInt[8L, 8]
import singleton.ops._
def demoString[P1 <: XString](implicit op : Reverse[P1] + P1) : op.Out = op.value
val bString : "cbaabc" = demoString["abc"]
import singleton.ops._
def demoBoolean[P1 <: XInt](implicit op : P1 < 0) : op.Out = op.value
val bBoolean1 : true = demoBoolean[-5]
val bBoolean2 : false = demoBoolean[5]
val bBoolean3 : false = demoBoolean[0]
import singleton.ops._
def demoRequire[P1 <: XInt](implicit op : Require[P1 < 0]) : op.Out = op.value
scala> demoRequire[-1]
demoRequire[-1]
res0: Boolean(true) = true
scala> demoRequire[1]
<console>:16: error: could not find implicit Out for parameter op: singleton.ops.Require[singleton.ops.<[1,0]]
       demoRequire[1]
import singleton.ops._
import shapeless._
val n = Nat(5)
//Converting Nat to Int singleton occurs implicitly
def demoNatToSing[L <: Nat](implicit p : L+L) : p.Out = p.value
val bSing10 : 10 = demoNatToSing[n.N]
//Converting Int singleton to Nat requires explicit `ToNat`
def demoSingToNat[L <: XInt](implicit op : ToNat[L+L]) : op.Out = op.value
val bNat10 : shapeless.nat._10 = demoSingToNat[5]
import singleton.ops._
def bigMul[L1 <: XLong, L2 <: XLong](implicit p : L1 * L2) : p.Out = p.value
scala> bigMul[32000L, 6400000L]
res2: Long = 204800000000

Contributors and participation

The singleton-ops project supports the Typelevel code of conduct and wants all of its channels (Gitter, GitHub, etc.) to be welcoming environments for everyone.