Skip to content

fthomas/singleton-ops

singleton-ops

GitHub Workflow StatuscodecovJoin the chat at https://gitter.im/fthomas/singleton-opsScaladexScala.js

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

Simple example:

importsingleton.ops._classMyVec[L]{defdoubleSize=newMyVec[2*L] defnSize[N] =newMyVec[N*L] defgetLength(implicitlength : SafeInt[L]) :Int= length } objectMyVec{implicitdefapply[L](implicitcheck : Require[L>0]) :MyVec[L] =newMyVec[L]() } valmyVec:MyVec[10] =MyVec[4+1].doubleSize valmyBadVec=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:

  • Char with Singleton (aliased as XChar)
  • Int with Singleton (aliased as XInt)
  • Long with Singleton (aliased as XLong)
  • Float with Singleton (aliased as XFloat)
  • Double with Singleton (aliased as XDouble)
  • String with Singleton (aliased as XString)
  • Boolean with Singleton (aliased as XBoolean)
  • Nat (from Shapeless)

Supported arithmetic operations:

  • type +[P1, P2]
  • type -[P1, P2]
  • type *[P1, P2]
  • type /[P1, P2]
  • type %[P1, P2]
  • type Abs[P1]
  • type Negate[P1]

Supported relational operations:

  • type ==[P1, P2]
  • type !=[P1, P2]
  • type >[P1, P2]
  • type <[P1, P2]
  • type >=[P1, P2]
  • type <=[P1, P2]
  • type Min[P1, P2]
  • type Max[P1, P2]

Supported logical operations:

  • type &&[P1, P2]
  • type ||[P1, P2]
  • type ![P1]

Supported explicit conversion operations:

  • type ToNat[P1]
  • type ToChar[P1]
  • type ToInt[P1]
  • type ToLong[P1]
  • type ToFloat[P1]
  • type ToDouble[P1]
  • type ToString[P1]

Supported string operations:

  • type Length[S]
  • type +[S1, S2] (concat)
  • type Reverse[S]
  • type CharAt[S, I]
  • type Substring[S, I]
  • type SubSequence[S, IBeg, IEnd]
  • type StartsWith[S, Prefix]
  • type EndsWith[S, Suffix]
  • type Head[S]
  • type Tail[S]
  • type Matches[S, Regex]
  • type FirstMatch[S, Regex]
  • type PrefixMatch[S, Regex]
  • type ReplaceFirstMatch[S, Regex, R]
  • type ReplaceAllMatches[S, Regex, R]

Supported constraints operations:

  • type Require[P1]

Supported control operations:

  • type ==>[A, B] (first A then B)
  • type ITE[I,T,E] (If (I) Then (T) Else (E))

Supported Aux Pattern interface:

  • type OpAuxNat[O <: Op, Ret_Out <: Nat]
  • type OpAuxChar[O <: Op, Ret_Out <: XChar]
  • type OpAuxInt[O <: Op, Ret_Out <: XInt]
  • type OpAuxLong[O <: Op, Ret_Out <: XLong]
  • type OpAuxFloat[O <: Op, Ret_Out <: XFloat]
  • type OpAuxDouble[O <: Op, Ret_Out <: XDouble]
  • type OpAuxString[O <: Op, Ret_Out <: XString]
  • type OpAuxBoolean[O <: Op, Ret_Out <: XBoolean]

Examples

  • Int type operations:
importsingleton.ops._defdemo[L<:XInt](implicitp : L*L+L) : p.Out= p.value valb:30= demo[5]
  • Long type operations:
importsingleton.ops._defdemoLong[L1<:XLong, L2<:XLong](implicitp : Min[L1*L1, L2+L2]) : p.Out= p.value valbLong1:1L= demoLong[1L, 5L] valbLong2:6L= demoLong[3L, 3L]
  • Double type operations:
importsingleton.ops._defdemoDouble[L1<:XDouble, L2<:XDouble](implicitp : L1/L2+1.0) : p.Out= p.value valbDouble:1.2= demoDouble[1.0, 5.0]
  • Combined Long and Int type operations:
importsingleton.ops._defdemoSumLongInt[L1<:XLong, L2<:XInt](implicitp : L1+L2) : p.Out= p.value valbSumLongInt:16L= demoSumLongInt[8L, 8]
  • String type operations:
importsingleton.ops._defdemoString[P1<:XString](implicitop : Reverse[P1] +P1) : op.Out= op.value valbString:"cbaabc"= demoString["abc"]
  • Boolean type operations:
importsingleton.ops._defdemoBoolean[P1<:XInt](implicitop : P1<0) : op.Out= op.value valbBoolean1:true= demoBoolean[-5] valbBoolean2:false= demoBoolean[5] valbBoolean3:false= demoBoolean[0]
  • Boolean type constraints:
importsingleton.ops._defdemoRequire[P1<:XInt](implicitop : 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 implicitOutfor parameter op: singleton.ops.Require[singleton.ops.<[1,0]] demoRequire[1]
  • Shapeless' Nat type operations:
importsingleton.ops._importshapeless._valn=Nat(5) //Converting Nat to Int singleton occurs implicitlydefdemoNatToSing[L<:Nat](implicitp : L+L) : p.Out= p.value valbSing10:10= demoNatToSing[n.N] //Converting Int singleton to Nat requires explicit `ToNat`defdemoSingToNat[L<:XInt](implicitop : ToNat[L+L]) : op.Out= op.value valbNat10: shapeless.nat._10 = demoSingToNat[5]
  • Working with large numbers doesn't slay the compiler:
importsingleton.ops._defbigMul[L1<:XLong, L2<:XLong](implicitp : L1*L2) : p.Out= p.value scala> bigMul[32000L, 6400000L] res2:Long=204800000000

Contributors and participation

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

About

Operations for primitive and String singleton types

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 12

Languages