This library provides type-level operations for Typelevel Scala with SIP-23.
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 requiredThe 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.
Char with Singleton(aliased asXChar)Int with Singleton(aliased asXInt)Long with Singleton(aliased asXLong)Float with Singleton(aliased asXFloat)Double with Singleton(aliased asXDouble)String with Singleton(aliased asXString)Boolean with Singleton(aliased asXBoolean)Nat(from Shapeless)
type +[P1, P2]type -[P1, P2]type *[P1, P2]type /[P1, P2]type %[P1, P2]type Abs[P1]type Negate[P1]
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]
type &&[P1, P2]type ||[P1, P2]type ![P1]
type ToNat[P1]type ToChar[P1]type ToInt[P1]type ToLong[P1]type ToFloat[P1]type ToDouble[P1]type ToString[P1]
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]
type Require[P1]
type ==>[A, B](first A then B)type ITE[I,T,E](If (I) Then (T) Else (E))
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]
Inttype operations:
importsingleton.ops._defdemo[L<:XInt](implicitp : L*L+L) : p.Out= p.value valb:30= demo[5]Longtype 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]Doubletype 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
LongandInttype operations:
importsingleton.ops._defdemoSumLongInt[L1<:XLong, L2<:XInt](implicitp : L1+L2) : p.Out= p.value valbSumLongInt:16L= demoSumLongInt[8L, 8]Stringtype operations:
importsingleton.ops._defdemoString[P1<:XString](implicitop : Reverse[P1] +P1) : op.Out= op.value valbString:"cbaabc"= demoString["abc"]Booleantype 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]Booleantype 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'
Nattype 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=204800000000The singleton-ops project supports the Typelevelcode of conduct and wants all of its channels (Gitter, GitHub, etc.) to be welcoming environments for everyone.