├── .github └── workflows │ ├── ci.yml │ └── clean.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.sbt ├── project ├── build.properties └── plugins.sbt ├── scripts └── release.sh └── src ├── main ├── scala │ ├── MatrixExample │ │ └── matrix.scala │ └── singleton │ │ ├── ops │ │ ├── OpContainer.scala │ │ ├── impl │ │ │ ├── GeneralMacros.scala │ │ │ ├── InterpolatorTest.scala │ │ │ ├── Op.scala │ │ │ ├── OpId.scala │ │ │ ├── OpMacros.scala │ │ │ └── util.scala │ │ └── package.scala │ │ └── twoface │ │ ├── Checked.scala │ │ ├── TwoFace.scala │ │ ├── impl │ │ ├── CaseClassSkipper.scala │ │ ├── CheckedShell.scala │ │ └── TwoFaceShell.scala │ │ └── package.scala ├── scala_2.13+ │ └── singleton │ │ ├── ops │ │ └── impl │ │ │ └── ListZipper.scala │ │ └── twoface │ │ └── impl │ │ ├── Checked0ParamAny.scala │ │ ├── Checked1ParamAny.scala │ │ └── TwoFaceAny.scala └── scala_2.13- │ └── singleton │ ├── ops │ └── impl │ │ └── ListZipper.scala │ └── twoface │ └── impl │ ├── Checked0ParamAny.scala │ ├── Checked1ParamAny.scala │ └── TwoFaceAny.scala └── test ├── scala └── singleton │ ├── TestUtils.scala │ ├── ops │ ├── AndSpec.scala │ ├── BTESpec.scala │ ├── BTSpec.scala │ ├── BitwiseAndSpec.scala │ ├── BitwiseOrSpec.scala │ ├── CharAtSpec.scala │ ├── ConcatSpec.scala │ ├── DivSpec.scala │ ├── EqSpec.scala │ ├── ExperimentingSpec.scala │ ├── GetArgSpec.scala │ ├── GetLHSArgSpec.scala │ ├── ITESpec.scala │ ├── IdSpec.scala │ ├── ImplicitConversionSpec.scala │ ├── LengthSpec.scala │ ├── MaxSpec.scala │ ├── MinSpec.scala │ ├── MinusSpec.scala │ ├── ModSpec.scala │ ├── MulSpec.scala │ ├── NEqSpec.scala │ ├── NegateSpec.scala │ ├── OrSpec.scala │ ├── PlusSpec.scala │ ├── RequireSpec.scala │ ├── ReverseSpec.scala │ ├── STESpec.scala │ ├── STSpec.scala │ ├── StringOpsSpec.scala │ ├── ToConversionSpec.scala │ ├── UnsupportedSpec.scala │ └── ValueExtractionSpec.scala │ └── twoface │ ├── CheckedBooleanSpec.scala │ ├── CheckedCharSpec.scala │ ├── CheckedDoubleSpec.scala │ ├── CheckedFloatSpec.scala │ ├── CheckedLongSpec.scala │ ├── TwoFaceBooleanSpec.scala │ ├── TwoFaceCharSpec.scala │ ├── TwoFaceDoubleSpec.scala │ ├── TwoFaceFloatSpec.scala │ ├── TwoFaceLongSpec.scala │ └── TwoFaceStringSpec.scala ├── scala_2.13+ └── singleton │ └── twoface │ ├── CheckedIntSpec.scala │ ├── CheckedStringSpec.scala │ └── TwoFaceIntSpec.scala └── scala_2.13- └── singleton └── twoface ├── CheckedIntSpec.scala ├── CheckedStringSpec.scala └── TwoFaceIntSpec.scala /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by sbt-github-actions using the 2 | # githubWorkflowGenerate task. You should add and commit this file to 3 | # your git repository. It goes without saying that you shouldn't edit 4 | # this file by hand! Instead, if you wish to make changes, you should 5 | # change your sbt build configuration to revise the workflow description 6 | # to meet your needs, then regenerate this file. 7 | 8 | name: Continuous Integration 9 | 10 | on: 11 | pull_request: 12 | branches: ['**'] 13 | push: 14 | branches: ['**'] 15 | tags: [v*] 16 | 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | 20 | jobs: 21 | build: 22 | name: Build and Test 23 | strategy: 24 | matrix: 25 | os: [ubuntu-latest] 26 | scala: [2.11.12, 2.12.8, 2.13.1] 27 | java: [temurin@8] 28 | runs-on: ${{ matrix.os }} 29 | steps: 30 | - name: Checkout current branch (full) 31 | uses: actions/checkout@v4 32 | with: 33 | fetch-depth: 0 34 | 35 | - name: Setup Java (temurin@8) 36 | if: matrix.java == 'temurin@8' 37 | uses: actions/setup-java@v4 38 | with: 39 | distribution: temurin 40 | java-version: 8 41 | cache: sbt 42 | 43 | - name: Check that workflows are up to date 44 | run: sbt '++ ${{ matrix.scala }}' githubWorkflowCheck 45 | 46 | - name: Build project 47 | run: sbt '++ ${{ matrix.scala }}' validate 48 | 49 | - name: Codecov 50 | uses: codecov/codecov-action@v1 51 | 52 | - name: Compress target directories 53 | run: tar cf targets.tar target .jvm/target .js/target project/target 54 | 55 | - name: Upload target directories 56 | uses: actions/upload-artifact@v4 57 | with: 58 | name: target-${{ matrix.os }}-${{ matrix.scala }}-${{ matrix.java }} 59 | path: targets.tar 60 | 61 | publish: 62 | name: Publish Artifacts 63 | needs: [build] 64 | if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) 65 | strategy: 66 | matrix: 67 | os: [ubuntu-latest] 68 | scala: [2.12.18] 69 | java: [temurin@8] 70 | runs-on: ${{ matrix.os }} 71 | steps: 72 | - name: Checkout current branch (full) 73 | uses: actions/checkout@v4 74 | with: 75 | fetch-depth: 0 76 | 77 | - name: Setup Java (temurin@8) 78 | if: matrix.java == 'temurin@8' 79 | uses: actions/setup-java@v4 80 | with: 81 | distribution: temurin 82 | java-version: 8 83 | cache: sbt 84 | 85 | - name: Download target directories (2.11.12) 86 | uses: actions/download-artifact@v4 87 | with: 88 | name: target-${{ matrix.os }}-2.11.12-${{ matrix.java }} 89 | 90 | - name: Inflate target directories (2.11.12) 91 | run: | 92 | tar xf targets.tar 93 | rm targets.tar 94 | 95 | - name: Download target directories (2.12.8) 96 | uses: actions/download-artifact@v4 97 | with: 98 | name: target-${{ matrix.os }}-2.12.8-${{ matrix.java }} 99 | 100 | - name: Inflate target directories (2.12.8) 101 | run: | 102 | tar xf targets.tar 103 | rm targets.tar 104 | 105 | - name: Download target directories (2.13.1) 106 | uses: actions/download-artifact@v4 107 | with: 108 | name: target-${{ matrix.os }}-2.13.1-${{ matrix.java }} 109 | 110 | - name: Inflate target directories (2.13.1) 111 | run: | 112 | tar xf targets.tar 113 | rm targets.tar 114 | 115 | - name: Publish JARs 116 | env: 117 | PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} 118 | PGP_SECRET: ${{ secrets.PGP_SECRET }} 119 | SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} 120 | SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} 121 | run: sbt ci-release 122 | -------------------------------------------------------------------------------- /.github/workflows/clean.yml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by sbt-github-actions using the 2 | # githubWorkflowGenerate task. You should add and commit this file to 3 | # your git repository. It goes without saying that you shouldn't edit 4 | # this file by hand! Instead, if you wish to make changes, you should 5 | # change your sbt build configuration to revise the workflow description 6 | # to meet your needs, then regenerate this file. 7 | 8 | name: Clean 9 | 10 | on: push 11 | 12 | jobs: 13 | delete-artifacts: 14 | name: Delete Artifacts 15 | runs-on: ubuntu-latest 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | steps: 19 | - name: Delete artifacts 20 | shell: bash {0} 21 | run: | 22 | # Customize those three lines with your repository and credentials: 23 | REPO=${GITHUB_API_URL}/repos/${{ github.repository }} 24 | 25 | # A shortcut to call GitHub API. 26 | ghapi() { curl --silent --location --user _:$GITHUB_TOKEN "$@"; } 27 | 28 | # A temporary file which receives HTTP response headers. 29 | TMPFILE=$(mktemp) 30 | 31 | # An associative array, key: artifact name, value: number of artifacts of that name. 32 | declare -A ARTCOUNT 33 | 34 | # Process all artifacts on this repository, loop on returned "pages". 35 | URL=$REPO/actions/artifacts 36 | while [[ -n "$URL" ]]; do 37 | 38 | # Get current page, get response headers in a temporary file. 39 | JSON=$(ghapi --dump-header $TMPFILE "$URL") 40 | 41 | # Get URL of next page. Will be empty if we are at the last page. 42 | URL=$(grep '^Link:' "$TMPFILE" | tr ',' '\n' | grep 'rel="next"' | head -1 | sed -e 's/.*.*//') 43 | rm -f $TMPFILE 44 | 45 | # Number of artifacts on this page: 46 | COUNT=$(( $(jq <<<$JSON -r '.artifacts | length') )) 47 | 48 | # Loop on all artifacts on this page. 49 | for ((i=0; $i < $COUNT; i++)); do 50 | 51 | # Get name of artifact and count instances of this name. 52 | name=$(jq <<<$JSON -r ".artifacts[$i].name?") 53 | ARTCOUNT[$name]=$(( $(( ${ARTCOUNT[$name]} )) + 1)) 54 | 55 | id=$(jq <<<$JSON -r ".artifacts[$i].id?") 56 | size=$(( $(jq <<<$JSON -r ".artifacts[$i].size_in_bytes?") )) 57 | printf "Deleting '%s' #%d, %'d bytes\n" $name ${ARTCOUNT[$name]} $size 58 | ghapi -X DELETE $REPO/actions/artifacts/$id 59 | done 60 | done 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | 4 | # sbt specific 5 | .cache 6 | .history 7 | .lib/ 8 | dist/* 9 | target/ 10 | lib_managed/ 11 | src_managed/ 12 | project/boot/ 13 | project/plugins/project/ 14 | 15 | # Scala-IDE specific 16 | .scala_dependencies 17 | .worksheet 18 | 19 | # IDEA specific 20 | .idea*/ 21 | /.bloop/ 22 | /.metals/ 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # singleton-ops 2 | [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/fthomas/singleton-ops/Continuous%20Integration)](https://github.com/fthomas/singleton-ops/actions?query=workflow%3A%22Continuous+Integration%22) 3 | [![codecov](https://codecov.io/gh/fthomas/singleton-ops/branch/master/graph/badge.svg)](https://codecov.io/gh/fthomas/singleton-ops) 4 | [![Join the chat at https://gitter.im/fthomas/singleton-ops](https://badges.gitter.im/fthomas/singleton-ops.svg)](https://gitter.im/fthomas/singleton-ops?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | [![Scaladex](https://index.scala-lang.org/fthomas/singleton-ops/singleton-ops/latest.svg?color=blue)](https://index.scala-lang.org/fthomas/singleton-ops) 6 | [![Scala.js](https://www.scala-js.org/assets/badges/scalajs-0.6.17.svg)](https://www.scala-js.org) 7 | 8 | This library provides type-level operations for [Typelevel Scala][typelevel-scala] with [SIP-23][sip-23]. 9 | ## Simple example: 10 | ```scala 11 | import singleton.ops._ 12 | 13 | class MyVec[L] { 14 | def doubleSize = new MyVec[2 * L] 15 | def nSize[N] = new MyVec[N * L] 16 | def getLength(implicit length : SafeInt[L]) : Int = length 17 | } 18 | object MyVec { 19 | implicit def apply[L](implicit check : Require[L > 0]) : MyVec[L] = new MyVec[L]() 20 | } 21 | val myVec : MyVec[10] = MyVec[4 + 1].doubleSize 22 | val myBadVec = MyVec[-1] //fails compilation, as required 23 | ``` 24 | 25 | --- 26 | ## Using singleton-ops 27 | 28 | 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. 29 | 30 | If you're using sbt, add the following to your build: 31 | 32 | ```sbt 33 | libraryDependencies ++= Seq( 34 | "eu.timepit" %% "singleton-ops" % "0.5.0" 35 | ) 36 | ``` 37 | If you're using scala.js use `%%%` instead 38 | 39 | ```sbt 40 | libraryDependencies ++= Seq( 41 | "eu.timepit" %%% "singleton-ops" % "0.5.0" 42 | ) 43 | ``` 44 | **Be sure to follow Typelevel Scala [instructions][typelevel-scala-use], to be able to use literal types in your code.** 45 | 46 | --- 47 | #### Supported types: 48 | * `Char with Singleton` (aliased as `XChar`) 49 | * `Int with Singleton` (aliased as `XInt`) 50 | * `Long with Singleton` (aliased as `XLong`) 51 | * `Float with Singleton` (aliased as `XFloat`) 52 | * `Double with Singleton` (aliased as `XDouble`) 53 | * `String with Singleton` (aliased as `XString`) 54 | * `Boolean with Singleton` (aliased as `XBoolean`) 55 | * `Nat` (from [Shapeless][shapeless]) 56 | 57 | #### Supported arithmetic operations: 58 | * `type +[P1, P2]` 59 | * `type -[P1, P2]` 60 | * `type *[P1, P2]` 61 | * `type /[P1, P2]` 62 | * `type %[P1, P2]` 63 | * `type Abs[P1]` 64 | * `type Negate[P1]` 65 | 66 | #### Supported relational operations: 67 | * `type ==[P1, P2]` 68 | * `type !=[P1, P2]` 69 | * `type >[P1, P2]` 70 | * `type <[P1, P2]` 71 | * `type >=[P1, P2]` 72 | * `type <=[P1, P2]` 73 | * `type Min[P1, P2]` 74 | * `type Max[P1, P2]` 75 | 76 | #### Supported logical operations: 77 | * `type &&[P1, P2]` 78 | * `type ||[P1, P2]` 79 | * `type ![P1]` 80 | 81 | #### Supported explicit conversion operations: 82 | * `type ToNat[P1]` 83 | * `type ToChar[P1]` 84 | * `type ToInt[P1]` 85 | * `type ToLong[P1]` 86 | * `type ToFloat[P1]` 87 | * `type ToDouble[P1]` 88 | * `type ToString[P1]` 89 | 90 | #### Supported string operations: 91 | * `type Length[S]` 92 | * `type +[S1, S2]` (concat) 93 | * `type Reverse[S]` 94 | * `type CharAt[S, I]` 95 | * `type Substring[S, I]` 96 | * `type SubSequence[S, IBeg, IEnd]` 97 | * `type StartsWith[S, Prefix]` 98 | * `type EndsWith[S, Suffix]` 99 | * `type Head[S]` 100 | * `type Tail[S]` 101 | * `type Matches[S, Regex]` 102 | * `type FirstMatch[S, Regex]` 103 | * `type PrefixMatch[S, Regex]` 104 | * `type ReplaceFirstMatch[S, Regex, R]` 105 | * `type ReplaceAllMatches[S, Regex, R]` 106 | 107 | #### Supported constraints operations: 108 | * `type Require[P1]` 109 | 110 | #### Supported control operations: 111 | * `type ==>[A, B]` (`first A then B`) 112 | * `type ITE[I,T,E]` (`If (I) Then (T) Else (E)`) 113 | 114 | #### Supported Aux Pattern interface: 115 | * `type OpAuxNat[O <: Op, Ret_Out <: Nat]` 116 | * `type OpAuxChar[O <: Op, Ret_Out <: XChar]` 117 | * `type OpAuxInt[O <: Op, Ret_Out <: XInt]` 118 | * `type OpAuxLong[O <: Op, Ret_Out <: XLong]` 119 | * `type OpAuxFloat[O <: Op, Ret_Out <: XFloat]` 120 | * `type OpAuxDouble[O <: Op, Ret_Out <: XDouble]` 121 | * `type OpAuxString[O <: Op, Ret_Out <: XString]` 122 | * `type OpAuxBoolean[O <: Op, Ret_Out <: XBoolean]` 123 | 124 | 125 | ## Examples 126 | 127 | * `Int` type operations: 128 | ```scala 129 | import singleton.ops._ 130 | def demo[L <: XInt](implicit p : L*L + L) : p.Out = p.value 131 | val b : 30 = demo[5] 132 | ``` 133 | * `Long` type operations: 134 | ```scala 135 | import singleton.ops._ 136 | def demoLong[L1 <: XLong, L2 <: XLong](implicit p : Min[L1*L1, L2+L2]) : p.Out = p.value 137 | val bLong1 : 1L = demoLong[1L, 5L] 138 | val bLong2 : 6L = demoLong[3L, 3L] 139 | ``` 140 | 141 | * `Double` type operations: 142 | ```scala 143 | import singleton.ops._ 144 | def demoDouble[L1 <: XDouble, L2 <: XDouble](implicit p : L1 / L2 + 1.0) : p.Out = p.value 145 | val bDouble : 1.2 = demoDouble[1.0, 5.0] 146 | ``` 147 | 148 | * Combined `Long` and `Int` type operations: 149 | ```scala 150 | import singleton.ops._ 151 | def demoSumLongInt[L1 <: XLong, L2 <: XInt](implicit p : L1 + L2) : p.Out = p.value 152 | val bSumLongInt : 16L = demoSumLongInt[8L, 8] 153 | ``` 154 | 155 | * `String` type operations: 156 | ```scala 157 | import singleton.ops._ 158 | def demoString[P1 <: XString](implicit op : Reverse[P1] + P1) : op.Out = op.value 159 | val bString : "cbaabc" = demoString["abc"] 160 | ``` 161 | 162 | * `Boolean` type operations: 163 | ```scala 164 | import singleton.ops._ 165 | def demoBoolean[P1 <: XInt](implicit op : P1 < 0) : op.Out = op.value 166 | val bBoolean1 : true = demoBoolean[-5] 167 | val bBoolean2 : false = demoBoolean[5] 168 | val bBoolean3 : false = demoBoolean[0] 169 | ``` 170 | 171 | * `Boolean` type constraints: 172 | ```scala 173 | import singleton.ops._ 174 | def demoRequire[P1 <: XInt](implicit op : Require[P1 < 0]) : op.Out = op.value 175 | scala> demoRequire[-1] 176 | demoRequire[-1] 177 | res0: Boolean(true) = true 178 | scala> demoRequire[1] 179 | :16: error: could not find implicit Out for parameter op: singleton.ops.Require[singleton.ops.<[1,0]] 180 | demoRequire[1] 181 | ``` 182 | 183 | * Shapeless' `Nat` type operations: 184 | ```scala 185 | import singleton.ops._ 186 | import shapeless._ 187 | val n = Nat(5) 188 | //Converting Nat to Int singleton occurs implicitly 189 | def demoNatToSing[L <: Nat](implicit p : L+L) : p.Out = p.value 190 | val bSing10 : 10 = demoNatToSing[n.N] 191 | //Converting Int singleton to Nat requires explicit `ToNat` 192 | def demoSingToNat[L <: XInt](implicit op : ToNat[L+L]) : op.Out = op.value 193 | val bNat10 : shapeless.nat._10 = demoSingToNat[5] 194 | ``` 195 | 196 | * Working with large numbers doesn't slay the compiler: 197 | ```scala 198 | import singleton.ops._ 199 | def bigMul[L1 <: XLong, L2 <: XLong](implicit p : L1 * L2) : p.Out = p.value 200 | scala> bigMul[32000L, 6400000L] 201 | res2: Long = 204800000000 202 | ``` 203 | 204 | ## Contributors and participation 205 | 206 | * [Frank S. Thomas](https://github.com/fthomas) 207 | * [Matthew Pocock](https://github.com/drdozer) 208 | * [Naoki Aoyama](https://github.com/aoiroaoino) 209 | * [Oron Port](https://github.com/soronpo) 210 | * [Carlos Quiroz](https://github.com/cquiroz) 211 | 212 | The singleton-ops project supports the [Typelevel][typelevel] 213 | [code of conduct][typelevel-coc] and wants all of its channels (Gitter, 214 | GitHub, etc.) to be welcoming environments for everyone. 215 | 216 | [shapeless]: https://github.com/milessabin/shapeless 217 | [sip-23]: http://docs.scala-lang.org/sips/pending/42.type.html 218 | [typelevel]: http://typelevel.org/ 219 | [typelevel-coc]: http://typelevel.org/conduct.html 220 | [typelevel-scala]: https://github.com/typelevel/scala 221 | [typelevel-scala-use]: https://github.com/typelevel/scala#how-to-use-typelevel-scala-4-with-sbt 222 | [twoface-discourse]: https://contributors.scala-lang.org/t/twoface-Outs-closing-the-gap-between-run-compile-time-functionality/869 223 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | import scala.sys.process._ 2 | import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType} 3 | 4 | /// variables 5 | 6 | val groupId = "eu.timepit" 7 | val projectName = "singleton-ops" 8 | val rootPkg = "singleton" 9 | val gitPubUrl = s"https://github.com/fthomas/$projectName.git" 10 | val gitDevUrl = s"git@github.com:fthomas/$projectName.git" 11 | 12 | val macroParadiseVersion = "2.1.1" 13 | val shapelessVersion = "2.3.7" 14 | val scalaCheckVersion = "1.15.2" 15 | 16 | val Scala_2_11 = "2.11.12" 17 | val Scala_2_12 = "2.12.8" 18 | val Scala_2_13 = "2.13.1" 19 | 20 | /// sbt-github-actions configuration 21 | 22 | ThisBuild / crossScalaVersions := Seq(Scala_2_11, Scala_2_12, Scala_2_13) 23 | ThisBuild / githubWorkflowTargetTags ++= Seq("v*") 24 | ThisBuild / githubWorkflowPublishTargetBranches := Seq( 25 | RefPredicate.Equals(Ref.Branch("master")), 26 | RefPredicate.StartsWith(Ref.Tag("v")) 27 | ) 28 | ThisBuild / githubWorkflowPublish := Seq( 29 | WorkflowStep.Run( 30 | List("sbt ci-release"), 31 | name = Some("Publish JARs"), 32 | env = Map( 33 | "PGP_PASSPHRASE" -> "${{ secrets.PGP_PASSPHRASE }}", 34 | "PGP_SECRET" -> "${{ secrets.PGP_SECRET }}", 35 | "SONATYPE_PASSWORD" -> "${{ secrets.SONATYPE_PASSWORD }}", 36 | "SONATYPE_USERNAME" -> "${{ secrets.SONATYPE_USERNAME }}" 37 | ) 38 | ) 39 | ) 40 | ThisBuild / githubWorkflowJavaVersions := Seq(JavaSpec.temurin("8")) 41 | ThisBuild / githubWorkflowBuild := 42 | Seq( 43 | WorkflowStep.Sbt(List("validate"), name = Some("Build project")), 44 | WorkflowStep.Use(UseRef.Public("codecov", "codecov-action", "v1"), name = Some("Codecov")) 45 | ) 46 | 47 | /// projects 48 | 49 | lazy val root = project.in(file(".")) 50 | .settings(commonSettings) 51 | .aggregate(singleton_opsJVM, singleton_opsJS) 52 | .settings( 53 | skip in publish := true, 54 | sources in Compile := Seq.empty, 55 | sources in Test := Seq.empty 56 | ) 57 | 58 | lazy val singleton_ops = crossProject(JVMPlatform, JSPlatform) 59 | .crossType(CrossType.Pure) 60 | .in(file(".")) 61 | .settings(commonSettings) 62 | .jsSettings( 63 | coverageEnabled := false 64 | ) 65 | 66 | lazy val singleton_opsJVM = singleton_ops.jvm 67 | lazy val singleton_opsJS = singleton_ops.js 68 | 69 | /// settings 70 | 71 | lazy val commonSettings = Def.settings( 72 | metadataSettings, 73 | compileSettings, 74 | scaladocSettings, 75 | miscSettings, 76 | crossVersionSharedSources 77 | ) 78 | 79 | lazy val metadataSettings = Def.settings( 80 | name := projectName, 81 | organization := groupId, 82 | homepage := Some(url(s"https://github.com/fthomas/$projectName")), 83 | startYear := Some(2016), 84 | licenses := Seq("Apache-2.0" -> url("https://www.apache.org/licenses/LICENSE-2.0")), 85 | scmInfo := Some(ScmInfo(homepage.value.get, s"scm:git:$gitPubUrl", Some(s"scm:git:$gitDevUrl"))), 86 | developers := List( 87 | Developer("fthomas", "Frank S. Thomas", "", url("https://github.com/fthomas")), 88 | Developer("soronpo", "Oron Port", "", url("https://github.com/soronpo")) 89 | ) 90 | ) 91 | 92 | lazy val crossVersionSharedSources: Seq[Setting[_]] = 93 | Seq(Compile, Test).map { sc => 94 | (unmanagedSourceDirectories in sc) ++= { 95 | (unmanagedSourceDirectories in sc ).value.flatMap { dir: File => 96 | if(dir.getName != "scala") Seq(dir) 97 | else 98 | CrossVersion.partialVersion(scalaVersion.value) match { 99 | case Some((2, y)) if y >= 13 => Seq(new File(dir.getPath + "_2.13+")) 100 | case Some((2, y)) if y >= 11 => Seq(new File(dir.getPath + "_2.13-")) 101 | } 102 | } 103 | } 104 | } 105 | 106 | lazy val compileSettings = Def.settings( 107 | scalaVersion := Scala_2_13, 108 | crossScalaVersions := Seq(Scala_2_11, Scala_2_12, Scala_2_13), 109 | scalaOrganization := "org.scala-lang", 110 | scalacOptions ++= Seq( 111 | "-deprecation", 112 | "-encoding", 113 | "UTF-8", 114 | "-feature", 115 | "-language:existentials", 116 | "-language:experimental.macros", 117 | "-language:higherKinds", 118 | "-language:implicitConversions", 119 | "-unchecked", 120 | "-Xfatal-warnings", 121 | // "-Xlint:-unused,_", 122 | // "-Yliteral-types", 123 | "-Ywarn-numeric-widen" 124 | // "-Ywarn-value-discard" 125 | ), 126 | scalacOptions ++= { 127 | CrossVersion.partialVersion(scalaVersion.value) match { 128 | case Some((2, v)) if v >= 13 => 129 | Nil 130 | case _ => 131 | Seq( 132 | "-Yno-adapted-args", 133 | "-Ywarn-unused-import", 134 | "-Xplugin-require:macroparadise" 135 | ) 136 | } 137 | }, 138 | scalacOptions in (Compile, console) -= "-Ywarn-unused-import", 139 | scalacOptions in (Test, console) -= "-Ywarn-unused-import", 140 | libraryDependencies ++= Seq( 141 | scalaOrganization.value % "scala-compiler" % scalaVersion.value, 142 | "com.chuusai" %%% "shapeless" % shapelessVersion, 143 | "org.scalacheck" %%% "scalacheck" % scalaCheckVersion % Test 144 | ), 145 | libraryDependencies ++= { 146 | CrossVersion.partialVersion(scalaVersion.value) match { 147 | // if scala 2.13+ is used, macro annotations are merged into scala-reflect 148 | // https://github.com/scala/scala/pull/6606 149 | case Some((2, v)) if v >= 13 => 150 | Seq() 151 | case _ => 152 | Seq( 153 | compilerPlugin("org.scalamacros" % "paradise" % macroParadiseVersion cross CrossVersion.patch) 154 | ) 155 | } 156 | } 157 | ) 158 | 159 | lazy val scaladocSettings = Def.settings( 160 | scalacOptions in (Compile, doc) ++= Seq( 161 | "-doc-source-url", 162 | scmInfo.value.get.browseUrl + "/tree/master€{FILE_PATH}.scala", 163 | "-sourcepath", 164 | baseDirectory.in(LocalRootProject).value.getAbsolutePath 165 | ), 166 | autoAPIMappings := true 167 | ) 168 | 169 | lazy val miscSettings = Def.settings( 170 | initialCommands += s""" 171 | import $rootPkg.ops._ 172 | import $rootPkg.twoface._ 173 | """ 174 | ) 175 | 176 | /// commands 177 | 178 | val validateCommands = Seq( 179 | "clean", 180 | "test:compile", 181 | "singleton_opsJS/test", 182 | "coverage", 183 | "singleton_opsJVM/test", 184 | "coverageReport", 185 | "coverageOff", 186 | "doc" 187 | ) 188 | addCommandAlias("validate", validateCommands.mkString(";", ";", "")) 189 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.9.9 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.github.sbt" % "sbt-github-actions" % "0.23.0") 2 | 3 | addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12") 4 | 5 | addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2") 6 | 7 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.3") 8 | 9 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.12.0") 10 | -------------------------------------------------------------------------------- /scripts/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | VERSION="$1" 4 | if [ -n "$VERSION" ]; then 5 | git tag -a -s v$VERSION -m "Releasing $VERSION" 6 | git push 7 | git push --tags 8 | fi 9 | -------------------------------------------------------------------------------- /src/main/scala/MatrixExample/matrix.scala: -------------------------------------------------------------------------------- 1 | //package MatrixExample 2 | // 3 | //import singleton.ops._ 4 | // 5 | //class Matrix[R <: XInt, C <: XInt] { 6 | // def + (that : Matrix[R, C]) : Matrix[R, C] = new Matrix[R, C] 7 | // def * (that : Double) : Matrix[R, C] = new Matrix[R, C] 8 | // def * [C2 <: XInt](that : Matrix[C, C2]) : Matrix[R, C2] = new Matrix[R, C2] 9 | // def transpose : Matrix[C, R] = new Matrix[C, R] 10 | //} 11 | // 12 | //class SquareMatrix[RC <: XInt] extends Matrix[RC, RC] { 13 | // def promoteBy[DeltaRC <: XInt](implicit p: RC + DeltaRC) : SquareMatrix[p.OutInt] = new SquareMatrix[p.OutInt] 14 | // 15 | //} 16 | // 17 | //class RVector[C <: XInt] extends Matrix[1, C] { 18 | // def IAmRVector() : Unit = println("I am Row Vector") 19 | //} 20 | // 21 | //class CVector[R <: XInt] extends Matrix[R, 1] { 22 | // def IAmCVector() : Unit = println("I am Column Vector") 23 | //} 24 | // 25 | //object Implicits { 26 | // implicit def e2m(e : Double) : Matrix[1, 1] = new Matrix[1, 1] 27 | // implicit def m2sm[RC <: XInt](m : Matrix[RC, RC]) : SquareMatrix[RC] = new SquareMatrix[RC] 28 | // //implicit def m2e[Double <: Element](m : Matrix[1, 1]) : Double = ??? 29 | // implicit def m2r[C <: XInt](m : Matrix[1, C]) = new RVector[C] 30 | // implicit def m2c[R <: XInt](m : Matrix[R, 1]) = new CVector[R] 31 | //} 32 | // 33 | -------------------------------------------------------------------------------- /src/main/scala/singleton/ops/OpContainer.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | object OpContainer { 4 | //Create an equivalence implicit rule with this `Eq` type 5 | //F - from type 6 | //T - to type 7 | //Wide - the T and F wide representation 8 | type Eq[F, T, Wide] = Require[ITE[IsNonLiteral[T], ImplicitFound[T =:= Wide], F == T]] 9 | 10 | //For an op container with a single argument, extend the companion object using this trait. 11 | //For example: 12 | //class Vec[Size] 13 | //object Vec extends OpContainer.Eq1[Vec, Int] 14 | //val v1 : Vec[2] = new Vec[1 + 1] 15 | //val vInt : Vec[Int] = new Vec[1 + 1] 16 | trait Eq1[C[F1], Wide1] { 17 | implicit def argCast[F1,T1](c : C[F1])(implicit eq : Eq[F1,T1,Wide1]) : C[T1] = c.asInstanceOf[C[T1]] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/scala/singleton/ops/impl/InterpolatorTest.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops.impl 2 | 3 | 4 | //This is just for testing the GetArg workaround a problem a string interpolator arguments are applied 5 | protected[singleton] object InterpolatorTest { 6 | trait Bar 7 | trait Tag[W] extends HasOut { 8 | type Out = W 9 | } 10 | type XBar[W] = Bar with Tag[W] 11 | 12 | final implicit class InterpolatorSyntax(val sc: StringContext) { 13 | def bar(args: Bar*)(implicit interpolator : Interpolator[Bar]) : interpolator.Out = interpolator.value 14 | } 15 | trait Interpolator[T] extends HasOut { 16 | type Out <: T 17 | val value : Out 18 | } 19 | 20 | object Interpolator { 21 | type Aux[T, Out0 <: T] = Interpolator[T]{type Out = Out0} 22 | implicit def ev[W] : Interpolator.Aux[Bar, XBar[W]] = macro Macro.interpolator 23 | } 24 | 25 | protected object Macro { 26 | object whitebox { type Context = scala.reflect.macros.whitebox.Context } 27 | def interpolator(c: whitebox.Context) : c.Tree = { 28 | import c.universe._ 29 | val widthTpe = c.internal.constantType(Constant(5)) 30 | 31 | q""" 32 | new singleton.ops.impl.InterpolatorTest.Interpolator[singleton.ops.impl.InterpolatorTest.Bar] { 33 | type Out = singleton.ops.impl.InterpolatorTest.XBar[$widthTpe] 34 | val value : Out = new singleton.ops.impl.InterpolatorTest.Bar{}.asInstanceOf[singleton.ops.impl.InterpolatorTest.XBar[$widthTpe]] 35 | } 36 | """ 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/scala/singleton/ops/impl/Op.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops.impl 2 | 3 | import shapeless.Nat 4 | 5 | trait HasOut extends Any with Serializable { 6 | type Out 7 | } 8 | 9 | trait Op extends HasOut { 10 | type OutWide 11 | type Out 12 | type OutNat <: Nat 13 | type OutChar <: Char with Singleton 14 | type OutInt <: Int with Singleton 15 | type OutLong <: Long with Singleton 16 | type OutFloat <: Float with Singleton 17 | type OutDouble <: Double with Singleton 18 | type OutString <: String with Singleton 19 | type OutBoolean <: Boolean with Singleton 20 | val value: Out 21 | val isLiteral : Boolean 22 | val valueWide: OutWide 23 | } 24 | 25 | protected[singleton] trait OpGen[O <: Op] {type Out; val value : Out} 26 | protected[singleton] object OpGen { 27 | type Aux[O <: Op, Ret_Out] = OpGen[O] {type Out = Ret_Out} 28 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.Out] = new OpGen[O] {type Out = o.Out; val value = o.value.asInstanceOf[o.Out]} 29 | implicit def getValue[O <: Op, Out](o : Aux[O, Out]) : Out = o.value 30 | } 31 | 32 | trait OpCast[T, O <: Op] extends HasOut {type Out <: T; val value : Out} 33 | 34 | 35 | @scala.annotation.implicitNotFound(msg = "Unable to prove type argument is a Nat.") 36 | trait OpNat[O <: Op] extends OpCast[Nat, O] 37 | object OpNat { 38 | type Aux[O <: Op, Ret_Out <: Nat] = OpNat[O] {type Out = Ret_Out} 39 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.OutNat] = new OpNat[O] {type Out = o.OutNat; val value = o.value.asInstanceOf[o.OutNat]} 40 | } 41 | 42 | @scala.annotation.implicitNotFound(msg = "Unable to prove type argument is a Char.") 43 | trait OpChar[O <: Op] extends OpCast[Char with Singleton, O] 44 | object OpChar { 45 | type Aux[O <: Op, Ret_Out <: Char with Singleton] = OpChar[O] {type Out = Ret_Out} 46 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.OutChar] = new OpChar[O] {type Out = o.OutChar; val value = o.value.asInstanceOf[o.OutChar]} 47 | implicit def conv[O <: Op](op : OpChar[O]) : Char = op.value 48 | } 49 | 50 | @scala.annotation.implicitNotFound(msg = "Unable to prove type argument is an Int.") 51 | trait OpInt[O <: Op] extends OpCast[Int with Singleton, O] 52 | object OpInt { 53 | type Aux[O <: Op, Ret_Out <: Int with Singleton] = OpInt[O] {type Out = Ret_Out} 54 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.OutInt] = new OpInt[O] {type Out = o.OutInt; val value = o.value.asInstanceOf[o.OutInt]} 55 | implicit def conv[O <: Op](op : OpInt[O]) : Int = op.value 56 | } 57 | 58 | @scala.annotation.implicitNotFound(msg = "Unable to prove type argument is a Long.") 59 | trait OpLong[O <: Op] extends OpCast[Long with Singleton, O] 60 | object OpLong { 61 | type Aux[O <: Op, Ret_Out <: Long with Singleton] = OpLong[O] {type Out = Ret_Out} 62 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.OutLong] = new OpLong[O] {type Out = o.OutLong; val value = o.value.asInstanceOf[o.OutLong]} 63 | implicit def conv[O <: Op](op : OpLong[O]) : Long = op.value 64 | } 65 | 66 | @scala.annotation.implicitNotFound(msg = "Unable to prove type argument is a Float.") 67 | trait OpFloat[O <: Op] extends OpCast[Float with Singleton, O] 68 | object OpFloat { 69 | type Aux[O <: Op, Ret_Out <: Float with Singleton] = OpFloat[O] {type Out = Ret_Out} 70 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.OutFloat] = new OpFloat[O] {type Out = o.OutFloat; val value = o.value.asInstanceOf[o.OutFloat]} 71 | implicit def conv[O <: Op](op : OpFloat[O]) : Float = op.value 72 | } 73 | 74 | @scala.annotation.implicitNotFound(msg = "Unable to prove type argument is a Double.") 75 | trait OpDouble[O <: Op] extends OpCast[Double with Singleton, O] 76 | object OpDouble { 77 | type Aux[O <: Op, Ret_Out <: Double with Singleton] = OpDouble[O] {type Out = Ret_Out} 78 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.OutDouble] = new OpDouble[O] {type Out = o.OutDouble; val value = o.value.asInstanceOf[o.OutDouble]} 79 | implicit def conv[O <: Op](op : OpDouble[O]) : Double = op.value 80 | } 81 | 82 | @scala.annotation.implicitNotFound(msg = "Unable to prove type argument is a String.") 83 | trait OpString[O <: Op] extends OpCast[String with Singleton, O] 84 | object OpString { 85 | type Aux[O <: Op, Ret_Out <: String with Singleton] = OpString[O] {type Out = Ret_Out} 86 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.OutString] = new OpString[O] {type Out = o.OutString; val value = o.value.asInstanceOf[o.OutString]} 87 | implicit def conv[O <: Op](op : OpString[O]) : String = op.value 88 | } 89 | 90 | @scala.annotation.implicitNotFound(msg = "Unable to prove type argument is a Boolean.") 91 | trait OpBoolean[O <: Op] extends OpCast[Boolean with Singleton, O] 92 | object OpBoolean { 93 | type Aux[O <: Op, Ret_Out <: Boolean with Singleton] = OpBoolean[O] {type Out = Ret_Out} 94 | implicit def impl[O <: Op](implicit o: O) : Aux[O, o.OutBoolean] = new OpBoolean[O] {type Out = o.OutBoolean; val value = o.value.asInstanceOf[o.OutBoolean]} 95 | implicit def conv[O <: Op](op : OpBoolean[O]) : Boolean = op.value 96 | } 97 | -------------------------------------------------------------------------------- /src/main/scala/singleton/ops/impl/OpId.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops.impl 2 | 3 | sealed trait Warn 4 | sealed trait NoSym 5 | sealed trait OpId 6 | object OpId { 7 | sealed trait Arg extends OpId //Argument 8 | sealed trait AcceptNonLiteral extends OpId 9 | sealed trait GetArg extends OpId 10 | sealed trait ImplicitFound extends OpId 11 | sealed trait EnumCount extends OpId 12 | sealed trait ITE extends OpId //If-Then-Else 13 | sealed trait ==> extends OpId 14 | sealed trait Id extends OpId 15 | sealed trait ! extends OpId 16 | sealed trait Require extends OpId 17 | sealed trait ToNat extends OpId 18 | sealed trait ToChar extends OpId 19 | sealed trait ToInt extends OpId 20 | sealed trait ToLong extends OpId 21 | sealed trait ToFloat extends OpId 22 | sealed trait ToDouble extends OpId 23 | sealed trait ToString extends OpId 24 | sealed trait IsNat extends OpId 25 | sealed trait IsChar extends OpId 26 | sealed trait IsInt extends OpId 27 | sealed trait IsLong extends OpId 28 | sealed trait IsFloat extends OpId 29 | sealed trait IsDouble extends OpId 30 | sealed trait IsString extends OpId 31 | sealed trait IsBoolean extends OpId 32 | sealed trait IsNonLiteral extends OpId 33 | sealed trait GetType extends OpId 34 | sealed trait Reverse extends OpId 35 | sealed trait Negate extends OpId 36 | sealed trait NumberOfLeadingZeros extends OpId 37 | sealed trait + extends OpId 38 | sealed trait - extends OpId 39 | sealed trait * extends OpId 40 | sealed trait / extends OpId 41 | sealed trait % extends OpId 42 | sealed trait < extends OpId 43 | sealed trait <= extends OpId 44 | sealed trait >= extends OpId 45 | sealed trait > extends OpId 46 | sealed trait == extends OpId 47 | sealed trait != extends OpId 48 | sealed trait || extends OpId 49 | sealed trait && extends OpId 50 | sealed trait BitwiseOr extends OpId 51 | sealed trait BitwiseAnd extends OpId 52 | sealed trait Min extends OpId 53 | sealed trait Max extends OpId 54 | sealed trait Substring extends OpId 55 | sealed trait SubSequence extends OpId 56 | sealed trait StartsWith extends OpId 57 | sealed trait EndsWith extends OpId 58 | sealed trait Head extends OpId 59 | sealed trait Tail extends OpId 60 | sealed trait Length extends OpId 61 | sealed trait CharAt extends OpId 62 | sealed trait Matches extends OpId 63 | sealed trait FirstMatch extends OpId 64 | sealed trait PrefixMatch extends OpId 65 | sealed trait ReplaceFirstMatch extends OpId 66 | sealed trait ReplaceAllMatches extends OpId 67 | sealed trait Abs extends OpId 68 | sealed trait Pow extends OpId 69 | sealed trait Floor extends OpId 70 | sealed trait Ceil extends OpId 71 | sealed trait Round extends OpId 72 | sealed trait Sin extends OpId 73 | sealed trait Cos extends OpId 74 | sealed trait Tan extends OpId 75 | sealed trait Sqrt extends OpId 76 | sealed trait Log extends OpId 77 | sealed trait Log10 extends OpId 78 | } 79 | -------------------------------------------------------------------------------- /src/main/scala/singleton/ops/impl/OpMacros.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops.impl 2 | import scala.reflect.macros.whitebox 3 | 4 | /******************************************************************************************************** 5 | * Three arguments type function macro 6 | *******************************************************************************************************/ 7 | @scala.annotation.implicitNotFound("Literal operation has failed.") 8 | trait OpMacro[N, S1, S2, S3] extends Op 9 | 10 | object OpMacro { 11 | type Aux[ 12 | N, 13 | S1, 14 | S2, 15 | S3, 16 | OutWide0, 17 | Out0, 18 | OutNat0 <: shapeless.Nat, 19 | OutChar0 <: Char with Singleton, 20 | OutInt0 <: Int with Singleton, 21 | OutLong0 <: Long with Singleton, 22 | OutFloat0 <: Float with Singleton, 23 | OutDouble0 <: Double with Singleton, 24 | OutString0 <: String with Singleton, 25 | OutBoolean0 <: Boolean with Singleton 26 | ] = OpMacro[N, S1, S2, S3] { 27 | type OutWide = OutWide0 28 | type Out = Out0 29 | type OutNat = OutNat0 30 | type OutChar = OutChar0 31 | type OutInt = OutInt0 32 | type OutLong = OutLong0 33 | type OutFloat = OutFloat0 34 | type OutDouble = OutDouble0 35 | type OutString = OutString0 36 | type OutBoolean = OutBoolean0 37 | } 38 | 39 | implicit def call[ 40 | N, 41 | S1, 42 | S2, 43 | S3, 44 | OutWide, 45 | Out, 46 | OutNat <: shapeless.Nat, 47 | OutChar <: Char with Singleton, 48 | OutInt <: Int with Singleton, 49 | OutLong <: Long with Singleton, 50 | OutFloat <: Float with Singleton, 51 | OutDouble <: Double with Singleton, 52 | OutString <: String with Singleton, 53 | OutBoolean <: Boolean with Singleton 54 | ]: Aux[ 55 | N, 56 | S1, 57 | S2, 58 | S3, 59 | OutWide, 60 | Out, 61 | OutNat, 62 | OutChar, 63 | OutInt, 64 | OutLong, 65 | OutFloat, 66 | OutDouble, 67 | OutString, 68 | OutBoolean 69 | ] = macro Macro.impl[N, S1, S2, S3] 70 | 71 | final class Macro(val c: whitebox.Context) extends GeneralMacros { 72 | def impl[ 73 | N : c.WeakTypeTag, 74 | S1: c.WeakTypeTag, 75 | S2: c.WeakTypeTag, 76 | S3: c.WeakTypeTag 77 | ]: c.Tree = 78 | materializeOpGen[OpMacro[N, S1, S2, S3]].usingFuncName 79 | } 80 | 81 | // implicit def valueOfOp[N, S1 : ValueOf, S2 : ValueOf, S3 : ValueOf] 82 | // (implicit op : OpMacro[N, S1, S2, S3]) : ValueOf[OpMacro[N, S1, S2, S3]] = new ValueOf(op) 83 | } 84 | /*******************************************************************************************************/ 85 | -------------------------------------------------------------------------------- /src/main/scala/singleton/ops/impl/util.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops.impl 2 | 3 | object nlz { //number of leading zeros 4 | def apply(value : Int) : Int = java.lang.Integer.numberOfLeadingZeros(value) 5 | def apply(value : Long) : Int = java.lang.Long.numberOfLeadingZeros(value) 6 | } 7 | 8 | object _require { 9 | @inline def apply(requirement: Boolean, message: => Any) = require(requirement, message) 10 | } 11 | 12 | object std { 13 | type Char = scala.Char 14 | type Int = scala.Int 15 | type Long = scala.Long 16 | type Float = scala.Float 17 | type Double = scala.Double 18 | type String = java.lang.String 19 | type Boolean = scala.Boolean 20 | } -------------------------------------------------------------------------------- /src/main/scala/singleton/twoface/Checked.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | import impl._ 3 | import singleton.ops.impl.NoSym 4 | 5 | object Checked { 6 | type F1[_] 7 | type F2[_,_] 8 | type Shell1[Cond[_], Msg[_], Arg1, Arg1Wide] = 9 | impl.CheckedShell1[Cond, Msg, NoSym, Arg1, Arg1Wide] 10 | type Shell1Sym[Cond[_], Msg[_], Sym, Arg1, Arg1Wide] = 11 | impl.CheckedShell1[Cond, Msg, Sym, Arg1, Arg1Wide] 12 | type Shell2[Cond[_,_], Msg[_,_], Arg1, Arg1Wide, Arg2, Arg2Wide] = 13 | impl.CheckedShell2[Cond, Msg, NoSym, Arg1, Arg1Wide, Arg2, Arg2Wide] 14 | type Shell2Sym[Cond[_,_], Msg[_,_], Sym, Arg1, Arg1Wide, Arg2, Arg2Wide] = 15 | impl.CheckedShell2[Cond, Msg, Sym, Arg1, Arg1Wide, Arg2, Arg2Wide] 16 | } 17 | 18 | object Checked0Param { 19 | trait Char extends Checked0ParamAny.Char.Alias 20 | trait Int extends Checked0ParamAny.Int.Alias 21 | trait Long extends Checked0ParamAny.Long.Alias 22 | trait Float extends Checked0ParamAny.Float.Alias 23 | trait Double extends Checked0ParamAny.Double.Alias 24 | trait String extends Checked0ParamAny.String.Alias 25 | trait Boolean extends Checked0ParamAny.Boolean.Alias 26 | } 27 | 28 | object Checked1Param { 29 | trait Char extends Checked1ParamAny.Char.Alias 30 | trait Int extends Checked1ParamAny.Int.Alias 31 | trait Long extends Checked1ParamAny.Long.Alias 32 | trait Float extends Checked1ParamAny.Float.Alias 33 | trait Double extends Checked1ParamAny.Double.Alias 34 | trait String extends Checked1ParamAny.String.Alias 35 | trait Boolean extends Checked1ParamAny.Boolean.Alias 36 | } 37 | -------------------------------------------------------------------------------- /src/main/scala/singleton/twoface/TwoFace.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import impl._ 4 | 5 | object TwoFace { 6 | type Char[T0] = TwoFaceAny.Char[T0] 7 | val Char = TwoFaceAny.Char 8 | 9 | type Int[T0] = TwoFaceAny.Int[T0] 10 | val Int = TwoFaceAny.Int 11 | 12 | type Long[T0] = TwoFaceAny.Long[T0] 13 | val Long = TwoFaceAny.Long 14 | 15 | type Float[T0] = TwoFaceAny.Float[T0] 16 | val Float = TwoFaceAny.Float 17 | 18 | type Double[T0] = TwoFaceAny.Double[T0] 19 | val Double = TwoFaceAny.Double 20 | 21 | type String[T0] = TwoFaceAny.String[T0] 22 | val String = TwoFaceAny.String 23 | 24 | type Boolean[T0] = TwoFaceAny.Boolean[T0] 25 | val Boolean = TwoFaceAny.Boolean 26 | } 27 | -------------------------------------------------------------------------------- /src/main/scala/singleton/twoface/impl/CaseClassSkipper.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface.impl 2 | 3 | import singleton.ops.impl.HasOut 4 | import singleton.twoface.TwoFace 5 | 6 | import scala.reflect.macros.whitebox 7 | 8 | sealed trait CaseClassSkipper[T <: HasOut] extends HasOut { 9 | type Out 10 | def apply(value : T => Any, fallBack : => Boolean) : Out 11 | } 12 | object CaseClassSkipper { 13 | type Aux[T <: HasOut, Out0] = CaseClassSkipper[T]{type Out = Out0} 14 | type TAux[T <: HasOut, Out0] = T {type Out = Out0} 15 | //Normal value retrieval 16 | implicit def evNormal[T <: HasOut](implicit t : T) : Aux[T, TwoFace.Boolean[t.Out]] = new CaseClassSkipper[T] { 17 | type Out = TwoFace.Boolean[t.Out] 18 | def apply(value: T => Any, fallBack: => Boolean): Out = value(t).asInstanceOf[Out] 19 | } 20 | //Fallback value retrieval 21 | case class Fail[T <: HasOut]() extends CaseClassSkipper[T] { 22 | type Out = Boolean 23 | def apply(value: T => Any, fallBack: => Boolean): Boolean = fallBack 24 | } 25 | implicit def evCC[T <: HasOut](implicit n : shapeless.Refute[T]) : Aux[T, Boolean] = macro evCCMacro[T] 26 | def evCCMacro[T <: HasOut](c: whitebox.Context)(n : c.Tree)(implicit wt : c.WeakTypeTag[T]) : c.Tree = { 27 | import c.universe._ 28 | val t = weakTypeOf[T] 29 | if (c.internal.enclosingOwner.owner.asClass.isCaseClass) 30 | q"_root_.singleton.twoface.impl.CaseClassSkipper.Fail[$t]()" 31 | else 32 | c.abort(c.enclosingPosition, "Could not find implicit for...") 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/main/scala/singleton/twoface/impl/CheckedShell.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface.impl 2 | 3 | import singleton.twoface._ 4 | 5 | 6 | trait CheckedShell1[Cond[_], Msg[_], Sym, Arg1, Arg1Wide] { 7 | def unsafeCheck(arg1 : => Arg1Wide) : Unit 8 | } 9 | 10 | object CheckedShell1 { 11 | implicit def ev[Cond[_], Msg[_], Sym, Arg1, Arg1Wide]( 12 | implicit 13 | cond : TwoFace.Boolean.Shell1[Cond, Arg1, Arg1Wide], 14 | msg : TwoFace.String.Shell1[Msg, Arg1, Arg1Wide], 15 | req : TwoFace.Boolean.RequireShell[Cond[Arg1], Msg[Arg1], Sym] 16 | ) : CheckedShell1[Cond, Msg, Sym, Arg1, Arg1Wide] = 17 | new CheckedShell1[Cond, Msg, Sym, Arg1, Arg1Wide] { 18 | def unsafeCheck(arg1: => Arg1Wide): Unit = req(cond(arg1).getValue, msg(arg1).getValue) 19 | } 20 | } 21 | 22 | trait CheckedShell1Builder[ChkShl[_,_], Cond[_], Msg[_], Arg1Wide] { 23 | def create[Sym, Arg1](_unsafeCheck : Arg1Wide => Unit) : ChkShl[Sym, Arg1] 24 | implicit def ev[Sym, Arg1]( 25 | implicit 26 | cond : TwoFace.Boolean.Shell1[Cond, Arg1, Arg1Wide], 27 | msg : TwoFace.String.Shell1[Msg, Arg1, Arg1Wide], 28 | req : TwoFace.Boolean.RequireShell[Cond[Arg1], Msg[Arg1], Sym] 29 | ) : ChkShl[Sym, Arg1] = create[Sym, Arg1](arg1 => req(cond(arg1).getValue, msg(arg1).getValue)) 30 | } 31 | 32 | 33 | trait CheckedShell2[Cond[_,_], Msg[_,_], Sym, Arg1, Arg1Wide, Arg2, Arg2Wide] { 34 | def unsafeCheck(arg1 : => Arg1Wide, arg2 : => Arg2Wide) : Unit 35 | } 36 | 37 | object CheckedShell2 { 38 | implicit def ev[Cond[_,_], Msg[_,_], Sym, Arg1, Arg1Wide, Arg2, Arg2Wide]( 39 | implicit 40 | cond : TwoFace.Boolean.Shell2[Cond, Arg1, Arg1Wide, Arg2, Arg2Wide], 41 | msg : TwoFace.String.Shell2[Msg, Arg1, Arg1Wide, Arg2, Arg2Wide], 42 | req : TwoFace.Boolean.RequireShell[Cond[Arg1, Arg2], Msg[Arg1, Arg2], Sym] 43 | ) : CheckedShell2[Cond, Msg, Sym, Arg1, Arg1Wide, Arg2, Arg2Wide] = 44 | new CheckedShell2[Cond, Msg, Sym, Arg1, Arg1Wide, Arg2, Arg2Wide] { 45 | def unsafeCheck(arg1: => Arg1Wide, arg2 : => Arg2Wide): Unit = 46 | req(cond(arg1, arg2).getValue, msg(arg1, arg2).getValue) 47 | } 48 | } 49 | 50 | trait CheckedShell2Builder[ChkShl[_,_,_], Cond[_,_], Msg[_,_], Arg1Wide, Arg2Wide] { 51 | def create[Sym, Arg1, Arg2](_unsafeCheck : (Arg1Wide, Arg2Wide) => Unit) : ChkShl[Sym, Arg1, Arg2] 52 | implicit def ev[Sym, Arg1, Arg2]( 53 | implicit 54 | cond : TwoFace.Boolean.Shell2[Cond, Arg1, Arg1Wide, Arg2, Arg2Wide], 55 | msg : TwoFace.String.Shell2[Msg, Arg1, Arg1Wide, Arg2, Arg2Wide], 56 | req : TwoFace.Boolean.RequireShell[Cond[Arg1, Arg2], Msg[Arg1, Arg2], Sym] 57 | ) : ChkShl[Sym, Arg1, Arg2] = create[Sym, Arg1, Arg2]((arg1, arg2) => req(cond(arg1, arg2).getValue, msg(arg1, arg2).getValue)) 58 | } 59 | -------------------------------------------------------------------------------- /src/main/scala/singleton/twoface/package.scala: -------------------------------------------------------------------------------- 1 | package singleton 2 | 3 | import singleton.ops._ 4 | import singleton.ops.impl.std 5 | 6 | package object twoface { 7 | import TwoFace._ 8 | 9 | def ifThenElse[I, T, E](ifArg: Boolean[I], thenArg : Char[T], elseArg : Char[E]) 10 | (implicit tfs : Char.Shell3[ITE, I, std.Boolean, T, std.Char, E, std.Char]) = tfs(ifArg.getValue, thenArg.getValue, elseArg.getValue) 11 | def ifThenElse[I, T, E](ifArg: Boolean[I], thenArg : Int[T], elseArg : Int[E]) 12 | (implicit tfs : Int.Shell3[ITE, I, std.Boolean, T, std.Int, E, std.Int]) = tfs(ifArg.getValue, thenArg.getValue, elseArg.getValue) 13 | def ifThenElse[I, T, E](ifArg: Boolean[I], thenArg : Long[T], elseArg : Long[E]) 14 | (implicit tfs : Long.Shell3[ITE, I, std.Boolean, T, std.Long, E, std.Long]) = tfs(ifArg.getValue, thenArg.getValue, elseArg.getValue) 15 | def ifThenElse[I, T, E](ifArg: Boolean[I], thenArg : Float[T], elseArg : Float[E]) 16 | (implicit tfs : Float.Shell3[ITE, I, std.Boolean, T, std.Float, E, std.Float]) = tfs(ifArg.getValue, thenArg.getValue, elseArg.getValue) 17 | def ifThenElse[I, T, E](ifArg: Boolean[I], thenArg : Double[T], elseArg : Double[E]) 18 | (implicit tfs : Double.Shell3[ITE, I, std.Boolean, T, std.Double, E, std.Double]) = tfs(ifArg.getValue, thenArg.getValue, elseArg.getValue) 19 | def ifThenElse[I, T, E](ifArg: Boolean[I], thenArg : String[T], elseArg : String[E]) 20 | (implicit tfs : String.Shell3[ITE, I, std.Boolean, T, std.String, E, std.String]) = tfs(ifArg.getValue, thenArg.getValue, elseArg.getValue) 21 | def ifThenElse[I, T, E](ifArg: Boolean[I], thenArg : Boolean[T], elseArg : Boolean[E]) 22 | (implicit tfs : Boolean.Shell3[ITE, I, std.Boolean, T, std.Boolean, E, std.Boolean]) = tfs(ifArg.getValue, thenArg.getValue, elseArg.getValue) 23 | 24 | def require[C, M](cond : Boolean[C], msg : String[M])(implicit tfs : Boolean.Shell2[RequireMsg, C, std.Boolean, M, std.String]) = tfs(cond.getValue, msg.getValue) 25 | 26 | object math { 27 | import singleton.ops.math._ 28 | val Pi = Double.create[Pi](scala.math.Pi) 29 | val E = Double.create[E](scala.math.E) 30 | 31 | def abs[T](t : Int[T])(implicit tfs : Int.Shell1[Abs, T, std.Int]) = tfs(t.getValue) 32 | def abs[T](t : Long[T])(implicit tfs : Long.Shell1[Abs, T, std.Long]) = tfs(t.getValue) 33 | def abs[T](t : Float[T])(implicit tfs : Float.Shell1[Abs, T, std.Float]) = tfs(t.getValue) 34 | def abs[T](t : Double[T])(implicit tfs : Double.Shell1[Abs, T, std.Double]) = tfs(t.getValue) 35 | 36 | def min[L, R](l : Int[L], r : Int[R])(implicit tfs : Int.Shell2[Min, L, std.Int, R, std.Int]) = tfs(l.getValue, r.getValue) 37 | def min[L, R](l : Long[L], r : Long[R])(implicit tfs : Long.Shell2[Min, L, std.Long, R, std.Long]) = tfs(l.getValue, r.getValue) 38 | def min[L, R](l : Float[L], r : Float[R])(implicit tfs : Float.Shell2[Min, L, std.Float, R, std.Float]) = tfs(l.getValue, r.getValue) 39 | def min[L, R](l : Double[L], r : Double[R])(implicit tfs : Double.Shell2[Min, L, std.Double, R, std.Double]) = tfs(l.getValue, r.getValue) 40 | 41 | def max[L, R](l : Int[L], r : Int[R])(implicit tfs : Int.Shell2[Max, L, std.Int, R, std.Int]) = tfs(l.getValue, r.getValue) 42 | def max[L, R](l : Long[L], r : Long[R])(implicit tfs : Long.Shell2[Max, L, std.Long, R, std.Long]) = tfs(l.getValue, r.getValue) 43 | def max[L, R](l : Float[L], r : Float[R])(implicit tfs : Float.Shell2[Max, L, std.Float, R, std.Float]) = tfs(l.getValue, r.getValue) 44 | def max[L, R](l : Double[L], r : Double[R])(implicit tfs : Double.Shell2[Max, L, std.Double, R, std.Double]) = tfs(l.getValue, r.getValue) 45 | 46 | def pow[L, R](l : Float[L], r : Float[R])(implicit tfs : Double.ShellD[Pow, L, std.Float, R, std.Float]) = tfs(l.getValue, r.getValue) 47 | def pow[L, R](l : Float[L], r : Double[R])(implicit tfs : Double.ShellD[Pow, L, std.Float, R, std.Double]) = tfs(l.getValue, r.getValue) 48 | def pow[L, R](l : Double[L], r : Float[R])(implicit tfs : Double.ShellD[Pow, L, std.Double, R, std.Float]) = tfs(l.getValue, r.getValue) 49 | def pow[L, R](l : Double[L], r : Double[R])(implicit tfs : Double.Shell2[Pow, L, std.Double, R, std.Double]) = tfs(l.getValue, r.getValue) 50 | 51 | def floor[T](t : Float[T])(implicit tfs : Double.Shell1D[Floor, T, std.Float]) = tfs(t.getValue) 52 | def floor[T](t : Double[T])(implicit tfs : Double.Shell1[Floor, T, std.Double]) = tfs(t.getValue) 53 | 54 | def ceil[T](t : Float[T])(implicit tfs : Double.Shell1D[Ceil, T, std.Float]) = tfs(t.getValue) 55 | def ceil[T](t : Double[T])(implicit tfs : Double.Shell1[Ceil, T, std.Double]) = tfs(t.getValue) 56 | 57 | def round[T](t : Float[T])(implicit tfs : Int.Shell1[Round, T, std.Float]) = tfs(t.getValue) 58 | def round[T](t : Double[T])(implicit tfs : Long.Shell1[Round, T, std.Double]) = tfs(t.getValue) 59 | 60 | def sin[T](t : Float[T])(implicit tfs : Double.Shell1D[Sin, T, std.Float]) = tfs(t.getValue) 61 | def sin[T](t : Double[T])(implicit tfs : Double.Shell1[Sin, T, std.Double]) = tfs(t.getValue) 62 | 63 | def cos[T](t : Float[T])(implicit tfs : Double.Shell1D[Cos, T, std.Float]) = tfs(t.getValue) 64 | def cos[T](t : Double[T])(implicit tfs : Double.Shell1[Cos, T, std.Double]) = tfs(t.getValue) 65 | 66 | def tan[T](t : Float[T])(implicit tfs : Double.Shell1D[Tan, T, std.Float]) = tfs(t.getValue) 67 | def tan[T](t : Double[T])(implicit tfs : Double.Shell1[Tan, T, std.Double]) = tfs(t.getValue) 68 | 69 | def sqrt[T](t : Float[T])(implicit tfs : Double.Shell1D[Sqrt, T, std.Float]) = tfs(t.getValue) 70 | def sqrt[T](t : Double[T])(implicit tfs : Double.Shell1[Sqrt, T, std.Double]) = tfs(t.getValue) 71 | 72 | def log[T](t : Float[T])(implicit tfs : Double.Shell1D[Log, T, std.Float]) = tfs(t.getValue) 73 | def log[T](t : Double[T])(implicit tfs : Double.Shell1[Log, T, std.Double]) = tfs(t.getValue) 74 | 75 | def log10[T](t : Float[T])(implicit tfs : Double.Shell1D[Log10, T, std.Float]) = tfs(t.getValue) 76 | def log10[T](t : Double[T])(implicit tfs : Double.Shell1[Log10, T, std.Double]) = tfs(t.getValue) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/scala_2.13+/singleton/ops/impl/ListZipper.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops.impl 2 | 3 | object ListZipper { 4 | def apply[T](list1 : List[T], list2 : List[T]) = list1 lazyZip list2 5 | } 6 | -------------------------------------------------------------------------------- /src/main/scala_2.13+/singleton/twoface/impl/Checked0ParamAny.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface.impl 2 | 3 | import singleton.ops._ 4 | import singleton.ops.impl._ 5 | 6 | import scala.reflect.macros.whitebox 7 | 8 | trait Checked0ParamAny[Chk[Cond0[_], Msg0[_], T0], Cond[_], Msg[_], Face, T] extends Any with TwoFaceAny[Face, T] { 9 | def unsafeCheck()(implicit shl : CheckedShell1[Cond, Msg, NoSym, Face, Face]) : Chk[Cond, Msg, T] = { 10 | shl.unsafeCheck(getValue) 11 | this.asInstanceOf[Chk[Cond, Msg, T]] 12 | } 13 | } 14 | 15 | object Checked0ParamAny { 16 | trait LP[Chk[Cond0[_], Msg0[_], T0], Face] { 17 | def create[Cond[_], Msg[_], T](value : Face) : Chk[Cond, Msg, T] 18 | 19 | //This is a hack to force Scalac to actually display the constructed error message in all cases 20 | //From some weird reason only direct macro calls displays the error in a case of an implicit conversion 21 | implicit def requireMsg[Cond[_], Msg[_], T >: Face, Out <: T](value : T) 22 | : Chk[Cond, Msg, Out] = macro Builder.Macro.fromNumValue[Chk[Cond,Msg,_], Cond[_], Msg[_], T] 23 | 24 | //from non-singleton values 25 | implicit def fromNumNonSing[Cond[_], Msg[_]](value : Face)( 26 | implicit req : ITE[IsNonLiteral[GetArg0], true, RequireMsg[Cond[GetArg0], Msg[GetArg0]]], di : DummyImplicit 27 | ) : Chk[Cond, Msg, Face] = create[Cond, Msg, Face](value) 28 | } 29 | 30 | trait Builder[Chk[Cond0[_], Msg0[_], T0], Face] extends LP[Chk, Face] { 31 | trait Alias { 32 | type Cond[T] 33 | type Msg[T] 34 | final type Checked[T] = Chk[Cond, Msg, T] 35 | final type CheckedShell[T] = CheckedShellSym[NoSym, T] 36 | final type CheckedShellSym[Sym, T] = CheckedShell1[Cond, Msg, Sym, T, Face] 37 | } 38 | 39 | //////////////////////////////////////////////////////////////////////////////////////// 40 | // Generic Implicit Conversions 41 | // Currently triggers good-code-red IntelliJ issue 42 | // https://youtrack.jetbrains.com/issue/SCL-13089 43 | //////////////////////////////////////////////////////////////////////////////////////// 44 | implicit def ev[Cond[_], Msg[_], T](implicit req : RequireMsg[Cond[T], Msg[T]], value : AcceptNonLiteral[Id[T]]) 45 | : Chk[Cond, Msg, T] = create[Cond, Msg, T](value.valueWide.asInstanceOf[Face]) 46 | 47 | implicit def fromNumSing[Cond[_], Msg[_], T <: Face with Singleton](value : T)( 48 | implicit req : RequireMsg[Cond[T], Msg[T]] 49 | ) : Chk[Cond, Msg, T] = create[Cond, Msg, T](value) 50 | 51 | implicit def fromTF[Cond[_], Msg[_], T](tfValue : TwoFaceAny[Face, T])( 52 | implicit req : RequireMsg[IsNonLiteral[T] || Cond[T], Msg[T]], di : DummyImplicit 53 | ) : Chk[Cond, Msg, T] = create[Cond, Msg, T](tfValue.getValue) 54 | 55 | implicit def argCast[Cond[_], Msg[_], F, T](c : Chk[Cond, Msg, F])( 56 | implicit eq : OpContainer.Eq[F, T, Face] 57 | ) : Chk[Cond, Msg, T] = c.asInstanceOf[Chk[Cond, Msg, T]] 58 | //////////////////////////////////////////////////////////////////////////////////////// 59 | } 60 | 61 | object Builder { 62 | final class Macro(val c: whitebox.Context) extends GeneralMacros { 63 | def fromNumValue[Chk, Cond, Msg, T](value : c.Tree)( 64 | implicit 65 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T] 66 | ): c.Tree = Checked0ParamMaterializer[Chk, Cond, Msg, T].fromNumValue(value) 67 | } 68 | } 69 | 70 | final class Char[Cond[_], Msg[_], T](val value : std.Char) extends 71 | Checked0ParamAny[Char, Cond, Msg, std.Char, T] with TwoFaceAny.Char[T] { 72 | @inline def getValue : std.Char = value 73 | } 74 | object Char extends Builder[Char, std.Char] { 75 | def create[Cond[_], Msg[_], T](value: std.Char): Char[Cond, Msg, T] = new Char[Cond, Msg, T](value) 76 | } 77 | 78 | @scala.annotation.implicitNotFound("haha") 79 | final class Int[Cond[_], Msg[_], T](val value : std.Int) extends 80 | Checked0ParamAny[Int, Cond, Msg, std.Int, T] with TwoFaceAny.Int[T] { 81 | @inline def getValue : std.Int = value 82 | } 83 | object Int extends Builder[Int, std.Int] { 84 | def create[Cond[_], Msg[_], T](value: std.Int): Int[Cond, Msg, T] = new Int[Cond, Msg, T](value) 85 | } 86 | 87 | final class Long[Cond[_], Msg[_], T](val value : std.Long) extends 88 | Checked0ParamAny[Long, Cond, Msg, std.Long, T] with TwoFaceAny.Long[T] { 89 | @inline def getValue : std.Long = value 90 | } 91 | object Long extends Builder[Long, std.Long] { 92 | def create[Cond[_], Msg[_], T](value: std.Long): Long[Cond, Msg, T] = new Long[Cond, Msg, T](value) 93 | } 94 | 95 | final class Float[Cond[_], Msg[_], T](val value : std.Float) extends 96 | Checked0ParamAny[Float, Cond, Msg, std.Float, T] with TwoFaceAny.Float[T] { 97 | @inline def getValue : std.Float = value 98 | } 99 | object Float extends Builder[Float, std.Float] { 100 | def create[Cond[_], Msg[_], T](value: std.Float): Float[Cond, Msg, T] = new Float[Cond, Msg, T](value) 101 | } 102 | 103 | final class Double[Cond[_], Msg[_], T](val value : std.Double) extends 104 | Checked0ParamAny[Double, Cond, Msg, std.Double, T] with TwoFaceAny.Double[T] { 105 | @inline def getValue : std.Double = value 106 | } 107 | object Double extends Builder[Double, std.Double] { 108 | def create[Cond[_], Msg[_], T](value: std.Double): Double[Cond, Msg, T] = new Double[Cond, Msg, T](value) 109 | } 110 | 111 | final class String[Cond[_], Msg[_], T](val value : std.String) extends 112 | Checked0ParamAny[String, Cond, Msg, std.String, T] with TwoFaceAny.String[T] { 113 | @inline def getValue : std.String = value 114 | } 115 | object String extends Builder[String, std.String] { 116 | def create[Cond[_], Msg[_], T](value: std.String): String[Cond, Msg, T] = new String[Cond, Msg, T](value) 117 | } 118 | 119 | final class Boolean[Cond[_], Msg[_], T](val value : std.Boolean) extends 120 | Checked0ParamAny[Boolean, Cond, Msg, std.Boolean, T] with TwoFaceAny.Boolean[T] { 121 | @inline def getValue : std.Boolean = value 122 | } 123 | object Boolean extends Builder[Boolean, std.Boolean] { 124 | def create[Cond[_], Msg[_], T](value: std.Boolean): Boolean[Cond, Msg, T] = new Boolean[Cond, Msg, T](value) 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /src/main/scala_2.13+/singleton/twoface/impl/Checked1ParamAny.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface.impl 2 | 3 | import singleton.ops._ 4 | import singleton.ops.impl._ 5 | 6 | import scala.reflect.macros.whitebox 7 | 8 | trait Checked1ParamAny[Chk[Cond0[_,_], Msg0[_,_], T0, ParamFace0, Param0], Cond[_,_], Msg[_,_], Face, T, ParamFace, Param] extends Any with TwoFaceAny[Face, T] { 9 | def unsafeCheck(p : ParamFace) 10 | (implicit shl : CheckedShell2[Cond, Msg, NoSym, Face, Face, ParamFace, ParamFace]) : Chk[Cond, Msg, T, ParamFace, Param] = { 11 | shl.unsafeCheck(getValue, p) 12 | this.asInstanceOf[Chk[Cond, Msg, T, ParamFace, Param]] 13 | } 14 | } 15 | 16 | object Checked1ParamAny { 17 | trait LP[Chk[Cond0[_,_], Msg0[_,_], T0, ParamFace0, Param0], Face] { 18 | def create[Cond[_,_], Msg[_,_], T, ParamFace, Param](value : Face) : Chk[Cond, Msg, T, ParamFace, Param] 19 | 20 | //This is a hack to force Scalac to actually display the constructed error message in all cases 21 | //From some weird reason only direct macro calls displays the error in a case of an implicit conversion 22 | implicit def requireMsg[Cond[_,_], Msg[_,_], T >: Face, ParamFace, Param, Out <: T](value : T) 23 | : Chk[Cond, Msg, Out, ParamFace, Param] = macro Builder.Macro.requireMsg[Chk[Cond,Msg,_,_,_], Cond[_,_], Msg[_,_], T, ParamFace, Param] 24 | 25 | //from non-singleton values 26 | implicit def fromNumNonSing[Cond[_,_], Msg[_,_], ParamFace, Param](value : Face)( 27 | implicit req : RequireMsg[IsNonLiteral[GetArg0] || IsNonLiteral[Param] || Cond[GetArg0, Param], Msg[GetArg0, Param]], 28 | ) : Chk[Cond, Msg, Face, ParamFace, Param] = create[Cond, Msg, Face, ParamFace, Param](value) 29 | } 30 | trait Builder[Chk[Cond0[_,_], Msg0[_,_], T0, ParamFace0, Param0], Face] extends LP[Chk, Face]{ 31 | trait Alias { 32 | type Cond[T, Param] 33 | type Msg[T, Param] 34 | type ParamFace 35 | final type Checked[T, Param] = Chk[Cond, Msg, T, ParamFace, Param] 36 | final type CheckedShell[T, Param] = CheckedShellSym[NoSym, T, Param] 37 | final type CheckedShellSym[Sym, T, Param] = CheckedShell2[Cond, Msg, Sym, T, Face, Param, ParamFace] 38 | } 39 | 40 | //////////////////////////////////////////////////////////////////////////////////////// 41 | // Generic Implicit Conversions 42 | // Currently triggers good-code-red IntelliJ issue 43 | // https://youtrack.jetbrains.com/issue/SCL-13089 44 | //////////////////////////////////////////////////////////////////////////////////////// 45 | implicit def ev[Cond[_,_], Msg[_,_], ParamFace, T, Param]( 46 | implicit req : RequireMsg[IsNonLiteral[Param] || Cond[T, Param], Msg[T, Param]], value : AcceptNonLiteral[Id[T]] 47 | ) : Chk[Cond, Msg, T, ParamFace, Param] = create[Cond, Msg, T, ParamFace, Param](value.valueWide.asInstanceOf[Face]) 48 | 49 | implicit def fromNumSing[Cond[_,_], Msg[_,_], T <: Face with Singleton, ParamFace, Param](value : T)( 50 | implicit req : RequireMsg[IsNonLiteral[Param] || Cond[T, Param], Msg[T, Param]] 51 | ) : Chk[Cond, Msg, T, ParamFace, Param] = create[Cond, Msg, T, ParamFace, Param](value) 52 | 53 | implicit def fromTF[Cond[_,_], Msg[_,_], T, ParamFace, Param](tfValue : TwoFaceAny[Face, T])( 54 | implicit req : RequireMsg[IsNonLiteral[T] || IsNonLiteral[Param] || Cond[T, Param], Msg[T, Param]], di : DummyImplicit 55 | ) : Chk[Cond, Msg, T, ParamFace, Param] = create[Cond, Msg, T, ParamFace, Param](tfValue.getValue) 56 | 57 | implicit def argCast[Cond[_,_], Msg[_,_], F, T, ParamFace, Param](c : Chk[Cond, Msg, F, ParamFace, Param])( 58 | implicit eq : OpContainer.Eq[F, T, Face] 59 | ) : Chk[Cond, Msg, T, ParamFace, Param] = c.asInstanceOf[Chk[Cond, Msg, T, ParamFace, Param]] 60 | //////////////////////////////////////////////////////////////////////////////////////// 61 | } 62 | 63 | object Builder { 64 | final class Macro(val c: whitebox.Context) extends GeneralMacros { 65 | def requireMsg[Chk, Cond, Msg, T, ParamFace, Param](value : c.Tree)( 66 | implicit 67 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T], paramFace : c.WeakTypeTag[ParamFace], p : c.WeakTypeTag[Param] 68 | ): c.Tree = Checked1ParamMaterializer[Chk, Cond, Msg, T, ParamFace, Param].fromNumValue(value) 69 | } 70 | } 71 | 72 | 73 | final class Char[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Char) extends 74 | Checked1ParamAny[Char, Cond, Msg, std.Char, T, ParamFace, Param] with TwoFaceAny.Char[T] { 75 | @inline def getValue : std.Char = value 76 | } 77 | object Char extends Builder[Char, std.Char] { 78 | override def create[Cond[_, _], Msg[_, _], T, ParamFace, Param](value: std.Char) 79 | : Char[Cond, Msg, T, ParamFace, Param] = new Char[Cond, Msg, T, ParamFace, Param](value) 80 | } 81 | 82 | final class Int[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Int) extends 83 | Checked1ParamAny[Int, Cond, Msg, std.Int, T, ParamFace, Param] with TwoFaceAny.Int[T] { 84 | @inline def getValue : std.Int = value 85 | } 86 | object Int extends Builder[Int, std.Int] { 87 | override def create[Cond[_, _], Msg[_, _], T, ParamFace, Param](value: std.Int) 88 | : Int[Cond, Msg, T, ParamFace, Param] = new Int[Cond, Msg, T, ParamFace, Param](value) 89 | } 90 | 91 | final class Long[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Long) extends 92 | Checked1ParamAny[Long, Cond, Msg, std.Long, T, ParamFace, Param] with TwoFaceAny.Long[T] { 93 | @inline def getValue : std.Long = value 94 | } 95 | object Long extends Builder[Long, std.Long] { 96 | override def create[Cond[_, _], Msg[_, _], T, ParamFace, Param](value: std.Long) 97 | : Long[Cond, Msg, T, ParamFace, Param] = new Long[Cond, Msg, T, ParamFace, Param](value) 98 | } 99 | 100 | final class Float[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Float) extends 101 | Checked1ParamAny[Float, Cond, Msg, std.Float, T, ParamFace, Param] with TwoFaceAny.Float[T] { 102 | @inline def getValue : std.Float = value 103 | } 104 | object Float extends Builder[Float, std.Float] { 105 | override def create[Cond[_, _], Msg[_, _], T, ParamFace, Param](value: std.Float) 106 | : Float[Cond, Msg, T, ParamFace, Param] = new Float[Cond, Msg, T, ParamFace, Param](value) 107 | } 108 | 109 | final class Double[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Double) extends 110 | Checked1ParamAny[Double, Cond, Msg, std.Double, T, ParamFace, Param] with TwoFaceAny.Double[T] { 111 | @inline def getValue : std.Double = value 112 | } 113 | object Double extends Builder[Double, std.Double] { 114 | override def create[Cond[_, _], Msg[_, _], T, ParamFace, Param](value: std.Double) 115 | : Double[Cond, Msg, T, ParamFace, Param] = new Double[Cond, Msg, T, ParamFace, Param](value) 116 | } 117 | 118 | final class String[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.String) extends 119 | Checked1ParamAny[String, Cond, Msg, std.String, T, ParamFace, Param] with TwoFaceAny.String[T] { 120 | @inline def getValue : std.String = value 121 | } 122 | object String extends Builder[String, std.String] { 123 | override def create[Cond[_, _], Msg[_, _], T, ParamFace, Param](value: std.String) 124 | : String[Cond, Msg, T, ParamFace, Param] = new String[Cond, Msg, T, ParamFace, Param](value) 125 | } 126 | 127 | final class Boolean[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Boolean) extends 128 | Checked1ParamAny[Boolean, Cond, Msg, std.Boolean, T, ParamFace, Param] with TwoFaceAny.Boolean[T] { 129 | @inline def getValue : std.Boolean = value 130 | } 131 | object Boolean extends Builder[Boolean, std.Boolean] { 132 | override def create[Cond[_, _], Msg[_, _], T, ParamFace, Param](value: std.Boolean) 133 | : Boolean[Cond, Msg, T, ParamFace, Param] = new Boolean[Cond, Msg, T, ParamFace, Param](value) 134 | } 135 | } 136 | 137 | -------------------------------------------------------------------------------- /src/main/scala_2.13-/singleton/ops/impl/ListZipper.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops.impl 2 | 3 | object ListZipper { 4 | def apply[T](list1 : List[T], list2 : List[T]) = (list1, list2).zipped 5 | } 6 | -------------------------------------------------------------------------------- /src/main/scala_2.13-/singleton/twoface/impl/Checked0ParamAny.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface.impl 2 | 3 | import singleton.ops._ 4 | import singleton.ops.impl._ 5 | 6 | import scala.reflect.macros.whitebox 7 | 8 | trait Checked0ParamAny[Chk[Cond0[_], Msg0[_], T0], Cond[_], Msg[_], Face, T] extends Any with TwoFaceAny[Face, T] { 9 | def unsafeCheck()(implicit shl : CheckedShell1[Cond, Msg, NoSym, Face, Face]) : Chk[Cond, Msg, T] = { 10 | shl.unsafeCheck(getValue) 11 | this.asInstanceOf[Chk[Cond, Msg, T]] 12 | } 13 | } 14 | 15 | object Checked0ParamAny { 16 | trait Builder[Chk[Cond0[_], Msg0[_], T0], Face] { 17 | trait Alias { 18 | type Cond[T] 19 | type Msg[T] 20 | final type Checked[T] = Chk[Cond, Msg, T] 21 | final type CheckedShell[T] = CheckedShellSym[NoSym, T] 22 | final type CheckedShellSym[Sym, T] = CheckedShell1[Cond, Msg, Sym, T, Face] 23 | } 24 | 25 | //////////////////////////////////////////////////////////////////////////////////////// 26 | // Generic Implicit Conversions 27 | // Currently triggers good-code-red IntelliJ issue 28 | // https://youtrack.jetbrains.com/issue/SCL-13089 29 | //////////////////////////////////////////////////////////////////////////////////////// 30 | implicit def ev[Cond[_], Msg[_], T](implicit value : AcceptNonLiteral[Id[T]]) 31 | : Chk[Cond, Msg, T] = macro Builder.Macro.fromOpImpl[Chk[Cond,Msg,_], Cond[_], Msg[_], T] 32 | 33 | implicit def fromNum[Cond[_], Msg[_], T >: Face, Out <: T](value : T) 34 | : Chk[Cond, Msg, Out] = macro Builder.Macro.fromNumValue[Chk[Cond,Msg,_], Cond[_], Msg[_], T] 35 | 36 | implicit def fromTF[Cond[_], Msg[_], T >: Face, Out <: T](value : TwoFaceAny[Face, T]) 37 | : Chk[Cond, Msg, Out] = macro Builder.Macro.fromTF[Chk[Cond,Msg,_], Cond[_], Msg[_], T] 38 | 39 | implicit def widen[Cond[_], Msg[_], T](value : Chk[Cond, Msg, T]) 40 | : Chk[Cond, Msg, Face] = macro Builder.Macro.widen[Chk[Cond,Msg,_], Cond[_], Msg[_], Face] 41 | //////////////////////////////////////////////////////////////////////////////////////// 42 | } 43 | 44 | object Builder { 45 | final class Macro(val c: whitebox.Context) extends GeneralMacros { 46 | def fromOpImpl[Chk, Cond, Msg, T](value : c.Tree)( 47 | implicit 48 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T] 49 | ): c.Tree = Checked0ParamMaterializer[Chk, Cond, Msg, T].fromOpImpl(value) 50 | 51 | def fromNumValue[Chk, Cond, Msg, T](value : c.Tree)( 52 | implicit 53 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T] 54 | ): c.Tree = Checked0ParamMaterializer[Chk, Cond, Msg, T].fromNumValue(value) 55 | 56 | def fromTF[Chk, Cond, Msg, T](value : c.Tree)( 57 | implicit 58 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T] 59 | ): c.Tree = Checked0ParamMaterializer[Chk, Cond, Msg, T].fromTF(value) 60 | 61 | def widen[Chk, Cond, Msg, T](value : c.Tree)( 62 | implicit 63 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T] 64 | ): c.Tree = Checked0ParamMaterializer[Chk, Cond, Msg, T].widen(value) 65 | } 66 | } 67 | 68 | final class Char[Cond[_], Msg[_], T](val value : std.Char) extends 69 | Checked0ParamAny[Char, Cond, Msg, std.Char, T] with TwoFaceAny.Char[T] { 70 | @inline def getValue : std.Char = value 71 | } 72 | object Char extends Builder[Char, std.Char] 73 | 74 | final class Int[Cond[_], Msg[_], T](val value : std.Int) extends 75 | Checked0ParamAny[Int, Cond, Msg, std.Int, T] with TwoFaceAny.Int[T] { 76 | @inline def getValue : std.Int = value 77 | } 78 | object Int extends Builder[Int, std.Int] 79 | 80 | final class Long[Cond[_], Msg[_], T](val value : std.Long) extends 81 | Checked0ParamAny[Long, Cond, Msg, std.Long, T] with TwoFaceAny.Long[T] { 82 | @inline def getValue : std.Long = value 83 | } 84 | object Long extends Builder[Long, std.Long] 85 | 86 | final class Float[Cond[_], Msg[_], T](val value : std.Float) extends 87 | Checked0ParamAny[Float, Cond, Msg, std.Float, T] with TwoFaceAny.Float[T] { 88 | @inline def getValue : std.Float = value 89 | } 90 | object Float extends Builder[Float, std.Float] 91 | 92 | final class Double[Cond[_], Msg[_], T](val value : std.Double) extends 93 | Checked0ParamAny[Double, Cond, Msg, std.Double, T] with TwoFaceAny.Double[T] { 94 | @inline def getValue : std.Double = value 95 | } 96 | object Double extends Builder[Double, std.Double] 97 | 98 | final class String[Cond[_], Msg[_], T](val value : std.String) extends 99 | Checked0ParamAny[String, Cond, Msg, std.String, T] with TwoFaceAny.String[T] { 100 | @inline def getValue : std.String = value 101 | } 102 | object String extends Builder[String, std.String] 103 | 104 | final class Boolean[Cond[_], Msg[_], T](val value : std.Boolean) extends 105 | Checked0ParamAny[Boolean, Cond, Msg, std.Boolean, T] with TwoFaceAny.Boolean[T] { 106 | @inline def getValue : std.Boolean = value 107 | } 108 | object Boolean extends Builder[Boolean, std.Boolean] 109 | } 110 | 111 | -------------------------------------------------------------------------------- /src/main/scala_2.13-/singleton/twoface/impl/Checked1ParamAny.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface.impl 2 | 3 | import singleton.ops._ 4 | import singleton.ops.impl._ 5 | 6 | import scala.reflect.macros.whitebox 7 | 8 | trait Checked1ParamAny[Chk[Cond0[_,_], Msg0[_,_], T0, ParamFace0, Param0], Cond[_,_], Msg[_,_], Face, T, ParamFace, Param] extends Any with TwoFaceAny[Face, T] { 9 | def unsafeCheck(p : ParamFace) 10 | (implicit shl : CheckedShell2[Cond, Msg, NoSym, Face, Face, ParamFace, ParamFace]) : Chk[Cond, Msg, T, ParamFace, Param] = { 11 | shl.unsafeCheck(getValue, p) 12 | this.asInstanceOf[Chk[Cond, Msg, T, ParamFace, Param]] 13 | } 14 | } 15 | 16 | object Checked1ParamAny { 17 | trait Builder[Chk[Cond0[_,_], Msg0[_,_], T0, ParamFace0, Param0], Face] { 18 | trait Alias { 19 | type Cond[T, Param] 20 | type Msg[T, Param] 21 | type ParamFace 22 | final type Checked[T, Param] = Chk[Cond, Msg, T, ParamFace, Param] 23 | final type CheckedShell[T, Param] = CheckedShellSym[NoSym, T, Param] 24 | final type CheckedShellSym[Sym, T, Param] = CheckedShell2[Cond, Msg, Sym, T, Face, Param, ParamFace] 25 | } 26 | 27 | //////////////////////////////////////////////////////////////////////////////////////// 28 | // Generic Implicit Conversions 29 | // Currently triggers good-code-red IntelliJ issue 30 | // https://youtrack.jetbrains.com/issue/SCL-13089 31 | //////////////////////////////////////////////////////////////////////////////////////// 32 | implicit def ev[Cond[_,_], Msg[_,_], ParamFace, T, Param](implicit value : AcceptNonLiteral[Id[T]]) 33 | : Chk[Cond, Msg, T, ParamFace, Param] = macro Builder.Macro.fromOpImpl[Chk[Cond,Msg,_,_,_], Cond[_,_], Msg[_,_], T, ParamFace, Param] 34 | 35 | implicit def fromNum[Cond[_,_], Msg[_,_], T >: Face, ParamFace, Param, Out <: T](value : T) 36 | : Chk[Cond, Msg, Out, ParamFace, Param] = macro Builder.Macro.fromNumValue[Chk[Cond,Msg,_,_,_], Cond[_,_], Msg[_,_], T, ParamFace, Param] 37 | 38 | implicit def fromTF[Cond[_,_], Msg[_,_], T >: Face, ParamFace, Param, Out <: T](value : TwoFaceAny[Face, T]) 39 | : Chk[Cond, Msg, Out, ParamFace, Param] = macro Builder.Macro.fromTF[Chk[Cond,Msg,_,_,_], Cond[_,_], Msg[_,_], T, ParamFace, Param] 40 | 41 | implicit def widen[Cond[_,_], Msg[_,_], T, ParamFace, Param](value : Chk[Cond, Msg, T, ParamFace, Param]) 42 | : Chk[Cond, Msg, Face, ParamFace, Param] = macro Builder.Macro.widen[Chk[Cond,Msg,_,_,_], Cond[_,_], Msg[_,_], Face, ParamFace, Param] 43 | //////////////////////////////////////////////////////////////////////////////////////// 44 | } 45 | 46 | object Builder { 47 | final class Macro(val c: whitebox.Context) extends GeneralMacros { 48 | def fromOpImpl[Chk, Cond, Msg, T, ParamFace, Param](value : c.Tree)( 49 | implicit 50 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T], paramFace : c.WeakTypeTag[ParamFace], p : c.WeakTypeTag[Param] 51 | ): c.Tree = Checked1ParamMaterializer[Chk, Cond, Msg, T, ParamFace, Param].fromOpImpl(value) 52 | 53 | def fromNumValue[Chk, Cond, Msg, T, ParamFace, Param](value : c.Tree)( 54 | implicit 55 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T], paramFace : c.WeakTypeTag[ParamFace], p : c.WeakTypeTag[Param] 56 | ): c.Tree = Checked1ParamMaterializer[Chk, Cond, Msg, T, ParamFace, Param].fromNumValue(value) 57 | 58 | def fromTF[Chk, Cond, Msg, T, ParamFace, Param](value : c.Tree)( 59 | implicit 60 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T], paramFace : c.WeakTypeTag[ParamFace], p : c.WeakTypeTag[Param] 61 | ): c.Tree = Checked1ParamMaterializer[Chk, Cond, Msg, T, ParamFace, Param].fromTF(value) 62 | 63 | def widen[Chk, Cond, Msg, T, ParamFace, Param](value : c.Tree)( 64 | implicit 65 | chk : c.WeakTypeTag[Chk], cond : c.WeakTypeTag[Cond], msg : c.WeakTypeTag[Msg], t : c.WeakTypeTag[T], paramFace : c.WeakTypeTag[ParamFace], p : c.WeakTypeTag[Param] 66 | ): c.Tree = Checked1ParamMaterializer[Chk, Cond, Msg, T, ParamFace, Param].widen(value) 67 | } 68 | } 69 | 70 | 71 | final class Char[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Char) extends 72 | Checked1ParamAny[Char, Cond, Msg, std.Char, T, ParamFace, Param] with TwoFaceAny.Char[T] { 73 | @inline def getValue : std.Char = value 74 | } 75 | object Char extends Builder[String, std.String] 76 | 77 | final class Int[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Int) extends 78 | Checked1ParamAny[Int, Cond, Msg, std.Int, T, ParamFace, Param] with TwoFaceAny.Int[T] { 79 | @inline def getValue : std.Int = value 80 | } 81 | object Int extends Builder[Int, std.Int] 82 | 83 | final class Long[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Long) extends 84 | Checked1ParamAny[Long, Cond, Msg, std.Long, T, ParamFace, Param] with TwoFaceAny.Long[T] { 85 | @inline def getValue : std.Long = value 86 | } 87 | object Long extends Builder[Long, std.Long] 88 | 89 | final class Float[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Float) extends 90 | Checked1ParamAny[Float, Cond, Msg, std.Float, T, ParamFace, Param] with TwoFaceAny.Float[T] { 91 | @inline def getValue : std.Float = value 92 | } 93 | object Float extends Builder[Float, std.Float] 94 | 95 | final class Double[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Double) extends 96 | Checked1ParamAny[Double, Cond, Msg, std.Double, T, ParamFace, Param] with TwoFaceAny.Double[T] { 97 | @inline def getValue : std.Double = value 98 | } 99 | object Double extends Builder[Double, std.Double] 100 | 101 | final class String[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.String) extends 102 | Checked1ParamAny[String, Cond, Msg, std.String, T, ParamFace, Param] with TwoFaceAny.String[T] { 103 | @inline def getValue : std.String = value 104 | } 105 | object String extends Builder[String, std.String] 106 | 107 | final class Boolean[Cond[_,_], Msg[_,_], T, ParamFace, Param](val value : std.Boolean) extends 108 | Checked1ParamAny[Boolean, Cond, Msg, std.Boolean, T, ParamFace, Param] with TwoFaceAny.Boolean[T] { 109 | @inline def getValue : std.Boolean = value 110 | } 111 | object Boolean extends Builder[Boolean, std.Boolean] 112 | } 113 | 114 | -------------------------------------------------------------------------------- /src/test/scala/singleton/TestUtils.scala: -------------------------------------------------------------------------------- 1 | package singleton 2 | 3 | import org.scalacheck.Prop 4 | import singleton.ops._ 5 | import singleton.twoface._ 6 | 7 | object TestUtils { 8 | def sameType[A, B](implicit ev: A =:= B): Boolean = true 9 | 10 | def wellTyped(body: => Unit): Prop = Prop.secure { 11 | body 12 | true 13 | } 14 | 15 | def illRun(body: => Unit) : Prop = { 16 | val isIll = try { 17 | body 18 | false 19 | } catch { 20 | case _ : Throwable => 21 | true 22 | } 23 | if (!isIll) 24 | assert(false, "Expected assertion did not occur") 25 | true 26 | } 27 | 28 | type Verify[OP, Expected] = Require[(OP == Expected) && ( 29 | (IsNat[OP] && IsNat[Expected]) || 30 | (IsChar[OP] && IsChar[Expected]) || 31 | (IsInt[OP] && IsInt[Expected]) || 32 | (IsLong[OP] && IsLong[Expected]) || 33 | (IsFloat[OP] && IsFloat[Expected]) || 34 | (IsDouble[OP] && IsDouble[Expected]) || 35 | (IsString[OP] && IsString[Expected]) || 36 | (IsBoolean[OP] && IsBoolean[Expected]) 37 | )] 38 | 39 | def verifyOp[OP, Expected](implicit verify: Verify[OP, Expected]) : Prop = wellTyped {} 40 | def verifyOp1Args[OP[_],L,Expected](implicit verify: Verify[OP[L], Expected]) : Prop = wellTyped {} 41 | def verifyOp2Args[OP[_,_],L,R,Expected](implicit verify: Verify[OP[L,R], Expected]) : Prop = wellTyped {} 42 | 43 | type VerifyTF[OP, Expected] = Require[ITE[IsNonLiteral[Expected], IsNonLiteral[OP], OP == Expected]] 44 | 45 | def verifyTFChar[OP, Expected](opResult : TwoFace.Char[OP], expectedResult : TwoFace.Char[Expected]) 46 | (implicit verify : VerifyTF[OP, Expected]) : Prop = { 47 | opResult.getValue == expectedResult.getValue 48 | } 49 | def verifyTFInt[OP, Expected](opResult : TwoFace.Int[OP], expectedResult : TwoFace.Int[Expected]) 50 | (implicit verify : VerifyTF[OP, Expected]) : Prop = { 51 | opResult.getValue == expectedResult.getValue 52 | } 53 | def verifyTFLong[OP, Expected](opResult : TwoFace.Long[OP], expectedResult : TwoFace.Long[Expected]) 54 | (implicit verify : VerifyTF[OP, Expected]) : Prop = { 55 | opResult.getValue == expectedResult.getValue 56 | } 57 | def verifyTFFloat[OP, Expected](opResult : TwoFace.Float[OP], expectedResult : TwoFace.Float[Expected]) 58 | (implicit verify : VerifyTF[OP, Expected]) : Prop = { 59 | opResult.getValue == expectedResult.getValue 60 | } 61 | def verifyTFDouble[OP, Expected](opResult : TwoFace.Double[OP], expectedResult : TwoFace.Double[Expected]) 62 | (implicit verify : VerifyTF[OP, Expected]) : Prop = { 63 | opResult.getValue == expectedResult.getValue 64 | } 65 | def verifyTFString[OP, Expected](opResult : TwoFace.String[OP], expectedResult : TwoFace.String[Expected]) 66 | (implicit verify : VerifyTF[OP, Expected]) : Prop = { 67 | opResult.getValue == expectedResult.getValue 68 | } 69 | def verifyTFBoolean[OP, Expected](opResult : TwoFace.Boolean[OP], expectedResult : TwoFace.Boolean[Expected]) 70 | (implicit verify : VerifyTF[OP, Expected]) : Prop = { 71 | opResult.getValue == expectedResult.getValue 72 | } 73 | 74 | //nf = unsafe. used to force a not-final value. e.g., nf(3) returns a non-literal 3 75 | def us[T](t : T) : T = { 76 | var ret = t 77 | ret 78 | } 79 | 80 | //Use to get the type of an object, when t.type is impossible 81 | trait Me { 82 | type T 83 | } 84 | def me[T0](t : T0) = new Me { 85 | type T = T0 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/AndSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class AndSpec extends Properties("&&") { 7 | property("truth table") = wellTyped { 8 | implicitly[Require[(True && True) == True]] 9 | implicitly[Require[(True && False) == False]] 10 | implicitly[Require[(False && True) == False]] 11 | implicitly[Require[(False && False) == False]] 12 | } 13 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/BTESpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.{Prop, Properties} 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class BTESpec extends Properties(">=") { 8 | type OP[L,R] = >=[L,R] 9 | type leftNat = shapeless.Nat._3 10 | type leftChar = W.`'\u0003'`.T 11 | type leftInt = W.`3`.T 12 | type leftLong = W.`3L`.T 13 | type leftFloat = W.`3.0f`.T 14 | type leftDouble = W.`3.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._2 19 | type rightChar = W.`'\u0002'`.T 20 | type rightInt = W.`2`.T 21 | type rightLong = W.`2L`.T 22 | type rightFloat = W.`2.0f`.T 23 | type rightDouble = W.`2.0`.T 24 | type rightString = W.`"Else"`.T 25 | type rightBoolean = False 26 | 27 | def verifyBTENum[L,R](implicit 28 | verifyFalse: Verify[R >= L, False], 29 | verifyTrue: Verify[L >= L, True], 30 | verifyTrue2: Verify[L >= R, True]) : Prop = wellTyped {} 31 | 32 | //////////////////////////////////////////////////////////////////////// 33 | // Nat op XXX 34 | //////////////////////////////////////////////////////////////////////// 35 | property("Nat, Nat arguments") = verifyBTENum[leftNat,rightNat] 36 | property("Nat, Int arguments") = verifyBTENum[leftNat,rightInt] 37 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 38 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 39 | //////////////////////////////////////////////////////////////////////// 40 | 41 | //////////////////////////////////////////////////////////////////////// 42 | // Char op XXX 43 | //////////////////////////////////////////////////////////////////////// 44 | property("Char, Char arguments") = verifyBTENum[leftChar,rightChar] 45 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 46 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 47 | //////////////////////////////////////////////////////////////////////// 48 | 49 | //////////////////////////////////////////////////////////////////////// 50 | // Int op XXX 51 | //////////////////////////////////////////////////////////////////////// 52 | property("Int, Nat arguments") = verifyBTENum[leftInt,rightNat] 53 | property("Int, Int arguments") = verifyBTENum[leftInt,rightInt] 54 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 55 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 56 | //////////////////////////////////////////////////////////////////////// 57 | 58 | //////////////////////////////////////////////////////////////////////// 59 | // Long op XXX 60 | //////////////////////////////////////////////////////////////////////// 61 | property("Long, Long arguments") = verifyBTENum[leftLong,rightLong] 62 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 63 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 64 | //////////////////////////////////////////////////////////////////////// 65 | 66 | //////////////////////////////////////////////////////////////////////// 67 | // Float op XXX 68 | //////////////////////////////////////////////////////////////////////// 69 | property("Float, Float arguments") = verifyBTENum[leftFloat,rightFloat] 70 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 71 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 72 | //////////////////////////////////////////////////////////////////////// 73 | 74 | //////////////////////////////////////////////////////////////////////// 75 | // Double op XXX 76 | //////////////////////////////////////////////////////////////////////// 77 | property("Double, Double arguments") = verifyBTENum[leftDouble,rightDouble] 78 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 79 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 80 | //////////////////////////////////////////////////////////////////////// 81 | 82 | //////////////////////////////////////////////////////////////////////// 83 | // String op XXX 84 | //////////////////////////////////////////////////////////////////////// 85 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 86 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 87 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 88 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 89 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 90 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 91 | property("String, String arguments") = {illTyped("""implicitly[OP[leftString,rightString]]"""); true} 92 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 93 | //////////////////////////////////////////////////////////////////////// 94 | 95 | //////////////////////////////////////////////////////////////////////// 96 | // Boolean op XXX 97 | //////////////////////////////////////////////////////////////////////// 98 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 99 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 100 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 101 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 102 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 103 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 104 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 105 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 106 | //////////////////////////////////////////////////////////////////////// 107 | } 108 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/BTSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.{Prop, Properties} 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class BTSpec extends Properties(">") { 8 | type OP[L,R] = >[L,R] 9 | type leftNat = shapeless.Nat._3 10 | type leftChar = W.`'\u0003'`.T 11 | type leftInt = W.`3`.T 12 | type leftLong = W.`3L`.T 13 | type leftFloat = W.`3.0f`.T 14 | type leftDouble = W.`3.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._2 19 | type rightChar = W.`'\u0002'`.T 20 | type rightInt = W.`2`.T 21 | type rightLong = W.`2L`.T 22 | type rightFloat = W.`2.0f`.T 23 | type rightDouble = W.`2.0`.T 24 | type rightString = W.`"Else"`.T 25 | 26 | def verifyBTNum[L,R](implicit 27 | verifyFalse: Verify[R > L, False], 28 | verifyFalse2: Verify[L > L, False], 29 | verifyTrue: Verify[L > R, True]) : Prop = wellTyped {} 30 | 31 | //////////////////////////////////////////////////////////////////////// 32 | // Nat op XXX 33 | //////////////////////////////////////////////////////////////////////// 34 | property("Nat, Nat arguments") = verifyBTNum[leftNat,rightNat] 35 | property("Nat, Int arguments") = verifyBTNum[leftNat,rightInt] 36 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 37 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 38 | //////////////////////////////////////////////////////////////////////// 39 | 40 | //////////////////////////////////////////////////////////////////////// 41 | // Char op XXX 42 | //////////////////////////////////////////////////////////////////////// 43 | property("Char, Char arguments") = verifyBTNum[leftChar,rightChar] 44 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 45 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 46 | //////////////////////////////////////////////////////////////////////// 47 | 48 | //////////////////////////////////////////////////////////////////////// 49 | // Int op XXX 50 | //////////////////////////////////////////////////////////////////////// 51 | property("Int, Nat arguments") = verifyBTNum[leftInt,rightNat] 52 | property("Int, Int arguments") = verifyBTNum[leftInt,rightInt] 53 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 54 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 55 | //////////////////////////////////////////////////////////////////////// 56 | 57 | //////////////////////////////////////////////////////////////////////// 58 | // Long op XXX 59 | //////////////////////////////////////////////////////////////////////// 60 | property("Long, Long arguments") = verifyBTNum[leftLong,rightLong] 61 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 62 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 63 | //////////////////////////////////////////////////////////////////////// 64 | 65 | //////////////////////////////////////////////////////////////////////// 66 | // Float op XXX 67 | //////////////////////////////////////////////////////////////////////// 68 | property("Float, Float arguments") = verifyBTNum[leftFloat,rightFloat] 69 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 70 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 71 | //////////////////////////////////////////////////////////////////////// 72 | 73 | //////////////////////////////////////////////////////////////////////// 74 | // Double op XXX 75 | //////////////////////////////////////////////////////////////////////// 76 | property("Double, Double arguments") = verifyBTNum[leftDouble,rightDouble] 77 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 78 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 79 | //////////////////////////////////////////////////////////////////////// 80 | 81 | //////////////////////////////////////////////////////////////////////// 82 | // String op XXX 83 | //////////////////////////////////////////////////////////////////////// 84 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 85 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 86 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 87 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 88 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 89 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 90 | property("String, String arguments") = {illTyped("""implicitly[OP[leftString,rightString]]"""); true} 91 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 92 | //////////////////////////////////////////////////////////////////////// 93 | 94 | //////////////////////////////////////////////////////////////////////// 95 | // Boolean op XXX 96 | //////////////////////////////////////////////////////////////////////// 97 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 98 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 99 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 100 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 101 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 102 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 103 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 104 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 105 | //////////////////////////////////////////////////////////////////////// 106 | } 107 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/BitwiseAndSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class BitwiseAndSpec extends Properties("BitwiseAnd") { 7 | property("Int checks") = wellTyped { 8 | implicitly[Require[(W.`9`.T BitwiseAnd W.`1`.T) == W.`1`.T]] 9 | implicitly[Require[(W.`9`.T BitwiseAnd W.`8`.T) == W.`8`.T]] 10 | implicitly[Require[(W.`9`.T BitwiseAnd W.`9`.T) == W.`9`.T]] 11 | implicitly[Require[(W.`9`.T BitwiseAnd W.`0`.T) == W.`0`.T]] 12 | } 13 | property("Long checks") = wellTyped { 14 | implicitly[Require[(W.`9L`.T BitwiseAnd W.`1L`.T) == W.`1L`.T]] 15 | implicitly[Require[(W.`9L`.T BitwiseAnd W.`8L`.T) == W.`8L`.T]] 16 | implicitly[Require[(W.`9L`.T BitwiseAnd W.`9L`.T) == W.`9L`.T]] 17 | implicitly[Require[(W.`9L`.T BitwiseAnd W.`0L`.T) == W.`0L`.T]] 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/BitwiseOrSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class BitwiseOrSpec extends Properties("BitwiseOr") { 7 | property("Int checks") = wellTyped { 8 | implicitly[Require[(W.`9`.T BitwiseOr W.`1`.T) == W.`9`.T]] 9 | implicitly[Require[(W.`9`.T BitwiseOr W.`8`.T) == W.`9`.T]] 10 | implicitly[Require[(W.`1`.T BitwiseOr W.`8`.T) == W.`9`.T]] 11 | implicitly[Require[(W.`9`.T BitwiseOr W.`0`.T) == W.`9`.T]] 12 | } 13 | property("Long checks") = wellTyped { 14 | implicitly[Require[(W.`9L`.T BitwiseOr W.`1L`.T) == W.`9L`.T]] 15 | implicitly[Require[(W.`9L`.T BitwiseOr W.`8L`.T) == W.`9L`.T]] 16 | implicitly[Require[(W.`1L`.T BitwiseOr W.`8L`.T) == W.`9L`.T]] 17 | implicitly[Require[(W.`9L`.T BitwiseOr W.`0L`.T) == W.`9L`.T]] 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/CharAtSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class CharAtSpec extends Properties("CharAt") { 7 | property("foobar.charAt(3) == b") = wellTyped { 8 | def charAt[P1 <: XString, P2 <: XInt](implicit op : CharAt[P1, P2]) : op.Out{} = op.value 9 | val r : W.`'b'`.T = charAt[W.`"foobar"`.T, W.`3`.T] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/ConcatSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class ConcatSpec extends Properties("Concat") { 7 | property("ab + cd == abcd") = wellTyped { 8 | def concat[P1 <: XString, P2 <: XString](implicit op : P1 + P2) : op.Out{} = op.value 9 | val r : W.`"abcd"`.T = concat[W.`"ab"`.T, W.`"cd"`.T] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/DivSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class DivSpec extends Properties("/") { 8 | type OP[L,R] = /[L,R] 9 | type leftNat = shapeless.Nat._12 10 | type leftChar = W.`'\u000C'`.T 11 | type leftInt = W.`12`.T 12 | type leftLong = W.`12L`.T 13 | type leftFloat = W.`12.0f`.T 14 | type leftDouble = W.`12.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._2 19 | type rightChar = W.`'\u0002'`.T 20 | type rightInt = W.`2`.T 21 | type rightLong = W.`2L`.T 22 | type rightFloat = W.`2.0f`.T 23 | type rightDouble = W.`2.0`.T 24 | type rightString = W.`"Else"`.T 25 | type rightBoolean = False 26 | 27 | type resultInt = W.`6`.T 28 | type resultLong = W.`6L`.T 29 | type resultFloat = W.`6.0f`.T 30 | type resultDouble = W.`6.0`.T 31 | 32 | //////////////////////////////////////////////////////////////////////// 33 | // Nat op XXX 34 | //////////////////////////////////////////////////////////////////////// 35 | property("Nat, Nat arguments") = verifyOp2Args[OP,leftNat,rightNat,resultInt] 36 | property("Nat, Int arguments") = verifyOp2Args[OP,leftNat,rightInt,resultInt] 37 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 38 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 39 | //////////////////////////////////////////////////////////////////////// 40 | 41 | //////////////////////////////////////////////////////////////////////// 42 | // Char op XXX 43 | //////////////////////////////////////////////////////////////////////// 44 | property("Char, Char arguments") = verifyOp2Args[OP,leftChar,rightChar,resultInt] 45 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 46 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 47 | //////////////////////////////////////////////////////////////////////// 48 | 49 | //////////////////////////////////////////////////////////////////////// 50 | // Int op XXX 51 | //////////////////////////////////////////////////////////////////////// 52 | property("Int, Nat arguments") = verifyOp2Args[OP,leftInt,rightNat,resultInt] 53 | property("Int, Int arguments") = verifyOp2Args[OP,leftInt,rightInt,resultInt] 54 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 55 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 56 | //////////////////////////////////////////////////////////////////////// 57 | 58 | //////////////////////////////////////////////////////////////////////// 59 | // Long op XXX 60 | //////////////////////////////////////////////////////////////////////// 61 | property("Long, Long arguments") = verifyOp2Args[OP,leftLong,rightLong,resultLong] 62 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 63 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 64 | //////////////////////////////////////////////////////////////////////// 65 | 66 | //////////////////////////////////////////////////////////////////////// 67 | // Float op XXX 68 | //////////////////////////////////////////////////////////////////////// 69 | property("Float, Float arguments") = verifyOp2Args[OP,leftFloat,rightFloat,resultFloat] 70 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 71 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 72 | //////////////////////////////////////////////////////////////////////// 73 | 74 | //////////////////////////////////////////////////////////////////////// 75 | // Double op XXX 76 | //////////////////////////////////////////////////////////////////////// 77 | property("Double, Double arguments") = verifyOp2Args[OP,leftDouble,rightDouble,resultDouble] 78 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 79 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 80 | //////////////////////////////////////////////////////////////////////// 81 | 82 | //////////////////////////////////////////////////////////////////////// 83 | // String op XXX 84 | //////////////////////////////////////////////////////////////////////// 85 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 86 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 87 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 88 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 89 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 90 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 91 | property("String, String arguments") = {illTyped("""implicitly[OP[leftString,rightString]]"""); true} 92 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 93 | //////////////////////////////////////////////////////////////////////// 94 | 95 | //////////////////////////////////////////////////////////////////////// 96 | // Boolean op XXX 97 | //////////////////////////////////////////////////////////////////////// 98 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 99 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 100 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 101 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 102 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 103 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 104 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 105 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 106 | //////////////////////////////////////////////////////////////////////// 107 | } 108 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/EqSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import org.scalacheck.Prop 7 | 8 | class EqSpec extends Properties("==") { 9 | property("Basic boolean arguments") = wellTyped { 10 | implicitly[Require[True == True]] 11 | implicitly[Require[False == False]] 12 | } 13 | property("Basic boolean arguments") = { 14 | illTyped("""implicitly[Require[True == False]]"""); 15 | illTyped("""implicitly[Require[False == True]]"""); 16 | true 17 | } 18 | 19 | type OP[L,R] = ==[L,R] 20 | type leftNat = shapeless.Nat._1 21 | type leftChar = W.`'\u0001'`.T 22 | type leftInt = W.`1`.T 23 | type leftLong = W.`1L`.T 24 | type leftFloat = W.`1.0f`.T 25 | type leftDouble = W.`1.0`.T 26 | type leftString = W.`"Something"`.T 27 | type leftBoolean = True 28 | 29 | type rightNat = shapeless.Nat._1 30 | type rightChar = W.`'\u0001'`.T 31 | type rightInt = W.`1`.T 32 | type rightLong = W.`1L`.T 33 | type rightFloat = W.`1.0f`.T 34 | type rightDouble = W.`1.0`.T 35 | type rightString = W.`"Else"`.T 36 | type rightBoolean = False 37 | 38 | def verifyEqNum[L,R](implicit 39 | verifyFalse: Verify[L == Negate[R], False], 40 | verifyTrue: Verify[L == R, True]) : Prop = wellTyped {} 41 | def verifyChar[L,R](implicit 42 | verifyFalse: Verify[L == ToChar[Negate[R]], False], 43 | verifyTrue: Verify[L == R, True]) : Prop = wellTyped {} 44 | 45 | //////////////////////////////////////////////////////////////////////// 46 | // Nat op XXX 47 | //////////////////////////////////////////////////////////////////////// 48 | property("Nat, Nat arguments") = verifyEqNum[leftNat,rightNat] 49 | property("Nat, Int arguments") = verifyEqNum[leftNat,rightInt] 50 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 51 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 52 | //////////////////////////////////////////////////////////////////////// 53 | 54 | //////////////////////////////////////////////////////////////////////// 55 | // Char op XXX 56 | //////////////////////////////////////////////////////////////////////// 57 | property("Char, Char arguments") = verifyChar[leftChar,rightChar] 58 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 59 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 60 | //////////////////////////////////////////////////////////////////////// 61 | 62 | //////////////////////////////////////////////////////////////////////// 63 | // Int op XXX 64 | //////////////////////////////////////////////////////////////////////// 65 | property("Int, Nat arguments") = verifyEqNum[leftInt,rightNat] 66 | property("Int, Int arguments") = verifyEqNum[leftInt,rightInt] 67 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 68 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 69 | //////////////////////////////////////////////////////////////////////// 70 | 71 | //////////////////////////////////////////////////////////////////////// 72 | // Long op XXX 73 | //////////////////////////////////////////////////////////////////////// 74 | property("Long, Long arguments") = verifyEqNum[leftLong,rightLong] 75 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 76 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 77 | //////////////////////////////////////////////////////////////////////// 78 | 79 | //////////////////////////////////////////////////////////////////////// 80 | // Float op XXX 81 | //////////////////////////////////////////////////////////////////////// 82 | property("Float, Float arguments") = verifyEqNum[leftFloat,rightFloat] 83 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 84 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 85 | //////////////////////////////////////////////////////////////////////// 86 | 87 | //////////////////////////////////////////////////////////////////////// 88 | // Double op XXX 89 | //////////////////////////////////////////////////////////////////////// 90 | property("Double, Double arguments") = verifyEqNum[leftDouble,rightDouble] 91 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 92 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 93 | //////////////////////////////////////////////////////////////////////// 94 | 95 | //////////////////////////////////////////////////////////////////////// 96 | // String op XXX 97 | //////////////////////////////////////////////////////////////////////// 98 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 99 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 100 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 101 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 102 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 103 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 104 | property("String, String arguments") = { 105 | verifyOp2Args[OP,leftString,leftString,True] 106 | verifyOp2Args[OP,leftString,rightString,False] 107 | } 108 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 109 | //////////////////////////////////////////////////////////////////////// 110 | 111 | //////////////////////////////////////////////////////////////////////// 112 | // Boolean op XXX 113 | //////////////////////////////////////////////////////////////////////// 114 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 115 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 116 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 117 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 118 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 119 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 120 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 121 | //////////////////////////////////////////////////////////////////////// 122 | } 123 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/GetArgSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class GetArgSpec extends Properties("GetArgSpec") { 8 | trait Conv { 9 | val value : Any 10 | } 11 | 12 | implicit class ConvInt(val value : Int)(implicit chk : CompileTime[GetArg0 < W.`50`.T]) extends Conv 13 | def smallerThan50(f : Conv) : Unit = {} 14 | 15 | implicit class BadConvLong(val value : Long)(implicit f : GetArg[W.`10`.T]) extends Conv 16 | 17 | implicit class FromInt[V <: Int](value : V) { 18 | def extendable[L <: Int](implicit left : GetLHSArg.Aux[W.`0`.T, L]) : FromInt[L] = new FromInt[L](left.value) 19 | } 20 | 21 | property("smallerThan50(1) OK") = wellTyped { 22 | smallerThan50(1) 23 | } 24 | property("smallerThan50(51) Compile-time fail") = wellTyped { 25 | illTyped("smallerThan50(51)") 26 | } 27 | property("Unsupported GetArg") = wellTyped { 28 | illTyped("implicitly[GetArg0]") //cannot be invoked without implicit conversion 29 | illTyped("smallerThan50(1L)") //Argument index too large in `BadConvLong` 30 | illTyped("implicitly[GetArg[W.`0.1`.T]]") //Bad argument (Double instead of Int) 31 | } 32 | property("Implicit conversion with applied type") = wellTyped { 33 | 1.extendable 34 | } 35 | 36 | object ByName 37 | def byName(arg : => Any)(implicit getArg : GetArg0) = getArg 38 | property("By name argument not evaluated until value is read") = { 39 | var byNameNotRead = true 40 | val b = byName({byNameNotRead = false; ByName}) 41 | val preRead = byNameNotRead 42 | val forceRead = b.value //now lazily invoked 43 | preRead && !byNameNotRead 44 | } 45 | 46 | val one = 1 47 | val two = 2 48 | val three = 2 49 | 50 | def testA[T, Out](value0 : T, value1 : T)(value2 : T)(value3 : T)(implicit ga : GetArg.Aux[W.`2`.T, Out]) = ga 51 | final val a = testA(10, 11)(12)(13) 52 | 53 | def testB[Out](value0 : Any, value1 : Any)(value2 : Any)(value3 : Any)(implicit ga : GetArg.Aux[W.`3`.T, Out]) = ga 54 | final val b = testB(one+one, two+two)(BigInt(3) + three)(13) 55 | 56 | property("GetArg.Aux OK") = wellTyped { 57 | implicitly[a.Out =:= W.`12`.T] 58 | implicitly[b.Out =:= W.`13`.T] 59 | } 60 | 61 | def bad_use[Out](implicit i : GetArg.Aux[W.`1.0`.T, Out] ) : Unit = {} 62 | property("Unsupported GetArg.Aux") = wellTyped { 63 | illTyped("bad_use") 64 | } 65 | 66 | import impl.InterpolatorTest._ 67 | 68 | trait Foo[W] { 69 | def +[R](that: Foo.Able[R]) : Unit = {} 70 | } 71 | object Foo { 72 | class Able[R](val right: R) 73 | object Able { 74 | implicit def ofXInt[R <: Int](right : Int)(implicit arg: GetArg.Aux[W.`0`.T, R]) : Able[R] = new Able[R](arg) 75 | implicit def ofBar[R <: Bar](right: Bar)(implicit arg: GetArg0.Aux[R]): Able[R] = new Able[R](right.asInstanceOf[R]) 76 | } 77 | } 78 | def foo(i: Int) = i 79 | 80 | property("GetArg combination compilation OK") = wellTyped { 81 | val z = new Foo[W.`5`.T] {} 82 | z + 1 83 | z + one 84 | z + (one + one) 85 | z + foo(1) 86 | z + foo(one) 87 | z + foo(one + one) 88 | Foo.Able.ofXInt(1) 89 | Foo.Able.ofXInt(one) 90 | Foo.Able.ofXInt(one + one) 91 | Foo.Able.ofXInt(foo(1)) 92 | Foo.Able.ofXInt(foo(one)) 93 | Foo.Able.ofXInt(foo(one + one)) 94 | } 95 | 96 | property("GetArg with string interpolation inputs") = wellTyped { 97 | val z = new Foo[W.`5`.T] {} 98 | val b5 = bar"5" 99 | z + b5 100 | z + bar"5" 101 | } 102 | 103 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/GetLHSArgSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class GetLHSArgSpec extends Properties("GetLHSArgSpec") { 8 | abstract class Conv[T](val value : T) { 9 | type Out = T 10 | } 11 | 12 | implicit class ConvInt(val int : Int) { 13 | def ext(implicit g : GetLHSArg0) : g.Out = g.value 14 | def <= [T, Out](that : Conv[T])(implicit g : OpAuxGen[AcceptNonLiteral[GetLHSArg0], Out]) : Conv[Out] = new Conv[Out](g.value){} 15 | def := [T, Out](that : Conv[T])(implicit g : GetLHSArg.Aux[W.`0`.T, Out]) : Conv[Out] = new Conv[Out](g){} 16 | } 17 | 18 | property("implicit class argument with GetLHSArg0") = { 19 | val c = new Conv(2){} 20 | val out = 12 <= c 21 | implicitly[out.Out =:= W.`12`.T] 22 | val out2 : W.`12`.T = 12.ext 23 | out.value == 12 24 | } 25 | 26 | property("implicit class argument with GetLHSArg.Aux") = { 27 | val c = new Conv(2){} 28 | val out = 12 := c 29 | implicitly[out.Out =:= W.`12`.T] 30 | out.value == 12 31 | } 32 | 33 | def bad(i : Int)(implicit arg : GetLHSArg0) : Unit ={} 34 | 35 | property("no LHS arguments fails macro") = wellTyped { 36 | illTyped("""bad(4)""", "Left-hand-side tree not found") 37 | } 38 | 39 | property("Unsupported GetLHSArg") = wellTyped { 40 | illTyped("implicitly[GetLHSArg[W.`-1`.T]]") //Bad argument (Negative Int) 41 | illTyped("implicitly[GetLHSArg[W.`0.1`.T]]") //Bad argument (Double instead of Int) 42 | } 43 | 44 | class Foo(value0 : Any, value1 : Any)(value2 : Any)(value3 : Any){ 45 | def getArg[I <: Int](idx : I)(implicit g : GetLHSArg[I]) : g.Out = g.value 46 | } 47 | 48 | property("Multiple LHS arguments") = wellTyped { 49 | val out0 : W.`1`.T = new Foo(1, "me")(3L)(true) getArg W(0).value 50 | val out1 : W.`"me"`.T = new Foo(1, "me")(3L)(true) getArg W(1).value 51 | val out2 : W.`3L`.T = new Foo(1, "me")(3L)(true) getArg W(2).value 52 | val out3 : W.`true`.T = new Foo(1, "me")(3L)(true) getArg W(3).value 53 | } 54 | 55 | 56 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/ITESpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class ITESpec extends Properties("ITE") { 7 | property("True condition") = wellTyped { 8 | implicitly[Require[ITE[True, W.`1`.T, W.`2`.T] == W.`1`.T]] 9 | } 10 | property("False condition") = wellTyped { 11 | implicitly[Require[ITE[False, W.`1`.T, W.`2`.T] == W.`2`.T]] 12 | } 13 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/IdSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class IdSpec extends Properties("Id") { 7 | property("Nat") = wellTyped { 8 | def getNat(implicit op : SafeNat[Id[shapeless.Nat._1]]) : op.Out = op.value 9 | val ret : shapeless.nat._1 = getNat 10 | } 11 | property("Char") = { 12 | val ret : Char = implicitly[SafeChar[Id[W.`'\u0001'`.T]]] 13 | ret == '\u0001' 14 | } 15 | property("Int") = { 16 | val ret : Int = implicitly[SafeInt[Id[W.`1`.T]]] 17 | ret == 1 18 | } 19 | property("Long") = { 20 | val ret : Long = implicitly[SafeLong[Id[W.`1L`.T]]] 21 | ret == 1L 22 | } 23 | property("Float") = { 24 | val ret : Float = implicitly[SafeFloat[Id[W.`1.0f`.T]]] 25 | ret == 1.0f 26 | } 27 | property("Double") = { 28 | val ret : Double = implicitly[SafeDouble[Id[W.`1.0`.T]]] 29 | ret == 1.0 30 | } 31 | property("String") = { 32 | val ret : String = implicitly[SafeString[Id[W.`"Something"`.T]]] 33 | ret == "Something" 34 | } 35 | property("Boolean") = { 36 | val ret : Boolean = implicitly[SafeBoolean[Id[W.`true`.T]]] 37 | ret == true 38 | } 39 | property("UpperBound") = { 40 | trait Foo[T] { 41 | type Width <: T 42 | val value : Int 43 | } 44 | val ret = new Foo[W.`1`.T]{ 45 | val value : Int = implicitly[SafeInt[Id[Width]]] 46 | } 47 | ret.value == 1 48 | } 49 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/ImplicitConversionSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | import shapeless.test.illTyped 6 | 7 | class ImplicitConversionSpec extends Properties("ImplicitConversion") { 8 | property("OpToOp") = wellTyped {val ret : W.`2`.T + W.`1`.T = implicitly[W.`4`.T - W.`1`.T]} 9 | property("OpToSingleton") = wellTyped {val ret : W.`3`.T = implicitly[W.`4`.T - W.`1`.T]} 10 | // property("SingletonToOp") = wellTyped {val ret : W.`2`.T + W.`1`.T = 3} 11 | property("Wrong OpToOp") = {illTyped("""val impl = implicitly[W.`4`.T - W.`2`.T]; val ret : W.`2`.T + W.`1`.T = impl"""); true} 12 | property("Wrong OpToSingleton") = {illTyped("""val impl = implicitly[W.`4`.T - W.`2`.T]; val ret : W.`3`.T = impl"""); true} 13 | property("Wrong SingletonToOp") = {illTyped("""val ret : W.`2`.T + W.`1`.T = W.`4`.T"""); true} 14 | // property("ValueOf[Op]") = wellTyped {val ret : W.`3`.T = valueOf[W.`4`.T - W.`1`.T]} 15 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/LengthSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class LengthSpec extends Properties("Length") { 7 | property("foobar.length == 6") = wellTyped { 8 | def length[P1 <: XString](implicit op : Length[P1]) : op.Out{} = op.value 9 | val r : W.`6`.T = length[W.`"foobar"`.T] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/MaxSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | import singleton.ops.math._ 6 | 7 | class MaxSpec extends Properties("Max") { 8 | property("Nat, right is maximum") = verifyOp2Args[Max,shapeless.Nat._1, shapeless.Nat._2, W.`2`.T] 9 | property("Nat, left is maximum") = verifyOp2Args[Max,shapeless.Nat._3, shapeless.Nat._2, W.`3`.T] 10 | property("Nat, equal") = verifyOp2Args[Max,shapeless.Nat._3, shapeless.Nat._3, W.`3`.T] 11 | property("Int, right is maximum") = verifyOp2Args[Max, W.`1`.T, W.`2`.T, W.`2`.T] 12 | property("Int, left is maximum") = verifyOp2Args[Max, W.`3`.T, W.`2`.T, W.`3`.T] 13 | property("Int, equal") = verifyOp2Args[Max, W.`3`.T, W.`3`.T, W.`3`.T] 14 | property("Long, right is maximum") = verifyOp2Args[Max, W.`1L`.T, W.`2L`.T, W.`2L`.T] 15 | property("Long, left is maximum") = verifyOp2Args[Max, W.`3L`.T, W.`2L`.T, W.`3L`.T] 16 | property("Long, equal") = verifyOp2Args[Max, W.`3L`.T, W.`3L`.T, W.`3L`.T] 17 | property("Float, right is maximum") = verifyOp2Args[Max, W.`1.0f`.T, W.`2.0f`.T, W.`2.0f`.T] 18 | property("Float, left is maximum") = verifyOp2Args[Max, W.`3.0f`.T, W.`2.0f`.T, W.`3.0f`.T] 19 | property("Float, equal") = verifyOp2Args[Max, W.`3.0f`.T, W.`3.0f`.T, W.`3.0f`.T] 20 | property("Double, right is maximum") = verifyOp2Args[Max, W.`1.0`.T, W.`2.0`.T, W.`2.0`.T] 21 | property("Double, left is maximum") = verifyOp2Args[Max, W.`3.0`.T, W.`2.0`.T, W.`3.0`.T] 22 | property("Double, equal") = verifyOp2Args[Max, W.`3.0`.T, W.`3.0`.T, W.`3.0`.T] 23 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/MinSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | import singleton.ops.math._ 6 | 7 | class MinSpec extends Properties("Min") { 8 | property("Nat, right is minimum") = verifyOp2Args[Min,shapeless.Nat._1, shapeless.Nat._2, W.`1`.T] 9 | property("Nat, left is minimum") = verifyOp2Args[Min,shapeless.Nat._3, shapeless.Nat._2, W.`2`.T] 10 | property("Nat, equal") = verifyOp2Args[Min,shapeless.Nat._3, shapeless.Nat._3, W.`3`.T] 11 | property("Int, right is minimum") = verifyOp2Args[Min, W.`1`.T, W.`2`.T, W.`1`.T] 12 | property("Int, left is minimum") = verifyOp2Args[Min, W.`3`.T, W.`2`.T, W.`2`.T] 13 | property("Int, equal") = verifyOp2Args[Min, W.`3`.T, W.`3`.T, W.`3`.T] 14 | property("Long, right is minimum") = verifyOp2Args[Min, W.`1L`.T, W.`2L`.T, W.`1L`.T] 15 | property("Long, left is minimum") = verifyOp2Args[Min, W.`3L`.T, W.`2L`.T, W.`2L`.T] 16 | property("Long, equal") = verifyOp2Args[Min, W.`3L`.T, W.`3L`.T, W.`3L`.T] 17 | property("Float, right is minimum") = verifyOp2Args[Min, W.`1.0f`.T, W.`2.0f`.T, W.`1.0f`.T] 18 | property("Float, left is minimum") = verifyOp2Args[Min, W.`3.0f`.T, W.`2.0f`.T, W.`2.0f`.T] 19 | property("Float, equal") = verifyOp2Args[Min, W.`3.0f`.T, W.`3.0f`.T, W.`3.0f`.T] 20 | property("Double, right is minimum") = verifyOp2Args[Min, W.`1.0`.T, W.`2.0`.T, W.`1.0`.T] 21 | property("Double, left is minimum") = verifyOp2Args[Min, W.`3.0`.T, W.`2.0`.T, W.`2.0`.T] 22 | property("Double, equal") = verifyOp2Args[Min, W.`3.0`.T, W.`3.0`.T, W.`3.0`.T] 23 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/MinusSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class MinusSpec extends Properties("-") { 8 | type OP[L,R] = -[L,R] 9 | type leftNat = shapeless.Nat._3 10 | type leftChar = W.`'\u0003'`.T 11 | type leftInt = W.`3`.T 12 | type leftLong = W.`3L`.T 13 | type leftFloat = W.`3.0f`.T 14 | type leftDouble = W.`3.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._2 19 | type rightChar = W.`'\u0002'`.T 20 | type rightInt = W.`2`.T 21 | type rightLong = W.`2L`.T 22 | type rightFloat = W.`2.0f`.T 23 | type rightDouble = W.`2.0`.T 24 | type rightString = W.`"Else"`.T 25 | type rightBoolean = False 26 | 27 | type resultChar = W.`'\u0001'`.T 28 | type resultInt = W.`1`.T 29 | type resultLong = W.`1L`.T 30 | type resultFloat = W.`1.0f`.T 31 | type resultDouble = W.`1.0`.T 32 | type resultString = W.`"SomethingElse"`.T 33 | type resultBoolean = W.`false`.T 34 | 35 | //////////////////////////////////////////////////////////////////////// 36 | // Nat op XXX 37 | //////////////////////////////////////////////////////////////////////// 38 | property("Nat, Nat arguments") = verifyOp2Args[OP,leftNat,rightNat,resultInt] 39 | property("Nat, Int arguments") = verifyOp2Args[OP,leftNat,rightInt,resultInt] 40 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 41 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 42 | //////////////////////////////////////////////////////////////////////// 43 | 44 | //////////////////////////////////////////////////////////////////////// 45 | // Char op XXX 46 | //////////////////////////////////////////////////////////////////////// 47 | property("Char, Char arguments") = verifyOp2Args[OP,leftChar,rightChar,resultInt] 48 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 49 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 50 | //////////////////////////////////////////////////////////////////////// 51 | 52 | //////////////////////////////////////////////////////////////////////// 53 | // Int op XXX 54 | //////////////////////////////////////////////////////////////////////// 55 | property("Int, Nat arguments") = verifyOp2Args[OP,leftInt,rightNat,resultInt] 56 | property("Int, Int arguments") = verifyOp2Args[OP,leftInt,rightInt,resultInt] 57 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 58 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 59 | //////////////////////////////////////////////////////////////////////// 60 | 61 | //////////////////////////////////////////////////////////////////////// 62 | // Long op XXX 63 | //////////////////////////////////////////////////////////////////////// 64 | property("Long, Long arguments") = verifyOp2Args[OP,leftLong,rightLong,resultLong] 65 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 66 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 67 | //////////////////////////////////////////////////////////////////////// 68 | 69 | //////////////////////////////////////////////////////////////////////// 70 | // Float op XXX 71 | //////////////////////////////////////////////////////////////////////// 72 | property("Float, Float arguments") = verifyOp2Args[OP,leftFloat,rightFloat,resultFloat] 73 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 74 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 75 | //////////////////////////////////////////////////////////////////////// 76 | 77 | //////////////////////////////////////////////////////////////////////// 78 | // Double op XXX 79 | //////////////////////////////////////////////////////////////////////// 80 | property("Double, Double arguments") = verifyOp2Args[OP,leftDouble,rightDouble,resultDouble] 81 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 82 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 83 | //////////////////////////////////////////////////////////////////////// 84 | 85 | //////////////////////////////////////////////////////////////////////// 86 | // String op XXX 87 | //////////////////////////////////////////////////////////////////////// 88 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 89 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 90 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 91 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 92 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 93 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 94 | property("String, String arguments") = {illTyped("""implicitly[OP[leftString,rightString]]"""); true} 95 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 96 | //////////////////////////////////////////////////////////////////////// 97 | 98 | //////////////////////////////////////////////////////////////////////// 99 | // Boolean op XXX 100 | //////////////////////////////////////////////////////////////////////// 101 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 102 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 103 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 104 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 105 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 106 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 107 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 108 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 109 | //////////////////////////////////////////////////////////////////////// 110 | } 111 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/ModSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class ModSpec extends Properties("%") { 8 | type OP[L,R] = %[L,R] 9 | type leftNat = shapeless.Nat._6 10 | type leftChar = W.`'\u0006'`.T 11 | type leftInt = W.`6`.T 12 | type leftLong = W.`6L`.T 13 | type leftFloat = W.`6.0f`.T 14 | type leftDouble = W.`6.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._7 19 | type rightChar = W.`'\u0007'`.T 20 | type rightInt = W.`7`.T 21 | type rightLong = W.`7L`.T 22 | type rightFloat = W.`7.0f`.T 23 | type rightDouble = W.`7.0`.T 24 | type rightString = W.`"Else"`.T 25 | type rightBoolean = False 26 | 27 | type resultInt = W.`6`.T 28 | type resultLong = W.`6L`.T 29 | type resultFloat = W.`6.0f`.T 30 | type resultDouble = W.`6.0`.T 31 | 32 | //////////////////////////////////////////////////////////////////////// 33 | // Nat op XXX 34 | //////////////////////////////////////////////////////////////////////// 35 | property("Nat, Nat arguments") = verifyOp2Args[OP,leftNat,rightNat,resultInt] 36 | property("Nat, Int arguments") = verifyOp2Args[OP,leftNat,rightInt,resultInt] 37 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 38 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 39 | //////////////////////////////////////////////////////////////////////// 40 | 41 | //////////////////////////////////////////////////////////////////////// 42 | // Char op XXX 43 | //////////////////////////////////////////////////////////////////////// 44 | property("Char, Char arguments") = verifyOp2Args[OP,leftChar,rightChar,resultInt] 45 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 46 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 47 | //////////////////////////////////////////////////////////////////////// 48 | 49 | //////////////////////////////////////////////////////////////////////// 50 | // Int op XXX 51 | //////////////////////////////////////////////////////////////////////// 52 | property("Int, Int arguments") = verifyOp2Args[OP,leftInt,rightInt,resultInt] 53 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 54 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 55 | //////////////////////////////////////////////////////////////////////// 56 | 57 | //////////////////////////////////////////////////////////////////////// 58 | // Long op XXX 59 | //////////////////////////////////////////////////////////////////////// 60 | property("Long, Long arguments") = verifyOp2Args[OP,leftLong,rightLong,resultLong] 61 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 62 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 63 | //////////////////////////////////////////////////////////////////////// 64 | 65 | //////////////////////////////////////////////////////////////////////// 66 | // Float op XXX 67 | //////////////////////////////////////////////////////////////////////// 68 | property("Float, Float arguments") = verifyOp2Args[OP,leftFloat,rightFloat,resultFloat] 69 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 70 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 71 | //////////////////////////////////////////////////////////////////////// 72 | 73 | //////////////////////////////////////////////////////////////////////// 74 | // Double op XXX 75 | //////////////////////////////////////////////////////////////////////// 76 | property("Double, Double arguments") = verifyOp2Args[OP,leftDouble,rightDouble,resultDouble] 77 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 78 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 79 | //////////////////////////////////////////////////////////////////////// 80 | 81 | //////////////////////////////////////////////////////////////////////// 82 | // String op XXX 83 | //////////////////////////////////////////////////////////////////////// 84 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 85 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 86 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 87 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 88 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 89 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 90 | property("String, String arguments") = {illTyped("""implicitly[OP[leftString,rightString]]"""); true} 91 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 92 | //////////////////////////////////////////////////////////////////////// 93 | 94 | //////////////////////////////////////////////////////////////////////// 95 | // Boolean op XXX 96 | //////////////////////////////////////////////////////////////////////// 97 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 98 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 99 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 100 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 101 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 102 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 103 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 104 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 105 | //////////////////////////////////////////////////////////////////////// 106 | } 107 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/MulSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class MulSpec extends Properties("*") { 8 | type OP[L,R] = *[L,R] 9 | type leftNat = shapeless.Nat._3 10 | type leftChar = W.`'\u0003'`.T 11 | type leftInt = W.`3`.T 12 | type leftLong = W.`3L`.T 13 | type leftFloat = W.`3.0f`.T 14 | type leftDouble = W.`3.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._2 19 | type rightChar = W.`'\u0002'`.T 20 | type rightInt = W.`2`.T 21 | type rightLong = W.`2L`.T 22 | type rightFloat = W.`2.0f`.T 23 | type rightDouble = W.`2.0`.T 24 | type rightString = W.`"Else"`.T 25 | type rightBoolean = False 26 | 27 | type resultInt = W.`6`.T 28 | type resultLong = W.`6L`.T 29 | type resultFloat = W.`6.0f`.T 30 | type resultDouble = W.`6.0`.T 31 | 32 | //////////////////////////////////////////////////////////////////////// 33 | // Nat op XXX 34 | //////////////////////////////////////////////////////////////////////// 35 | property("Nat, Nat arguments") = verifyOp2Args[OP,leftNat,rightNat,resultInt] 36 | property("Nat, Int arguments") = verifyOp2Args[OP,leftNat,rightInt,resultInt] 37 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 38 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 39 | //////////////////////////////////////////////////////////////////////// 40 | 41 | //////////////////////////////////////////////////////////////////////// 42 | // Char op XXX 43 | //////////////////////////////////////////////////////////////////////// 44 | property("Char, Char arguments") = verifyOp2Args[OP,leftChar,rightChar,resultInt] 45 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 46 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 47 | //////////////////////////////////////////////////////////////////////// 48 | 49 | //////////////////////////////////////////////////////////////////////// 50 | // Int op XXX 51 | //////////////////////////////////////////////////////////////////////// 52 | property("Int, Nat arguments") = verifyOp2Args[OP,leftInt,rightNat,resultInt] 53 | property("Int, Int arguments") = verifyOp2Args[OP,leftInt,rightInt,resultInt] 54 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 55 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 56 | //////////////////////////////////////////////////////////////////////// 57 | 58 | //////////////////////////////////////////////////////////////////////// 59 | // Long op XXX 60 | //////////////////////////////////////////////////////////////////////// 61 | property("Long, Long arguments") = verifyOp2Args[OP,leftLong,rightLong,resultLong] 62 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 63 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 64 | //////////////////////////////////////////////////////////////////////// 65 | 66 | //////////////////////////////////////////////////////////////////////// 67 | // Float op XXX 68 | //////////////////////////////////////////////////////////////////////// 69 | property("Float, Float arguments") = verifyOp2Args[OP,leftFloat,rightFloat,resultFloat] 70 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 71 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 72 | //////////////////////////////////////////////////////////////////////// 73 | 74 | //////////////////////////////////////////////////////////////////////// 75 | // Double op XXX 76 | //////////////////////////////////////////////////////////////////////// 77 | property("Double, Double arguments") = verifyOp2Args[OP,leftDouble,rightDouble,resultDouble] 78 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 79 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 80 | //////////////////////////////////////////////////////////////////////// 81 | 82 | //////////////////////////////////////////////////////////////////////// 83 | // String op XXX 84 | //////////////////////////////////////////////////////////////////////// 85 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 86 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 87 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 88 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 89 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 90 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 91 | property("String, String arguments") = {illTyped("""implicitly[OP[leftString,rightString]]"""); true} 92 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 93 | //////////////////////////////////////////////////////////////////////// 94 | 95 | //////////////////////////////////////////////////////////////////////// 96 | // Boolean op XXX 97 | //////////////////////////////////////////////////////////////////////// 98 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 99 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 100 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 101 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 102 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 103 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 104 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 105 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 106 | //////////////////////////////////////////////////////////////////////// 107 | } 108 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/NEqSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.{Prop, Properties} 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class NEqSpec extends Properties("!=") { 8 | property("Basic boolean arguments") = wellTyped { 9 | implicitly[Require[False != True]] 10 | implicitly[Require[True != False]] 11 | } 12 | property("Basic boolean arguments") = { 13 | illTyped("""implicitly[Require[True != True]]"""); 14 | illTyped("""implicitly[Require[False != False]]"""); 15 | true 16 | } 17 | 18 | type OP[L,R] = !=[L,R] 19 | type leftNat = shapeless.Nat._1 20 | type leftChar = W.`'\u0001'`.T 21 | type leftInt = W.`1`.T 22 | type leftLong = W.`1L`.T 23 | type leftFloat = W.`1.0f`.T 24 | type leftDouble = W.`1.0`.T 25 | type leftString = W.`"Something"`.T 26 | type leftBoolean = True 27 | 28 | type rightNat = shapeless.Nat._1 29 | type rightChar = W.`'\u0001'`.T 30 | type rightInt = W.`1`.T 31 | type rightLong = W.`1L`.T 32 | type rightFloat = W.`1.0f`.T 33 | type rightDouble = W.`1.0`.T 34 | type rightString = W.`"Else"`.T 35 | type rightBoolean = False 36 | 37 | def verifyNEqNum[L,R](implicit 38 | verifyFalse: Verify[L != Negate[R], True], 39 | verifyTrue: Verify[L != R, False]) : Prop = wellTyped {} 40 | def verifyChar[L,R](implicit 41 | verifyFalse: Verify[L != ToChar[Negate[R]], True], 42 | verifyTrue: Verify[L != R, False]) : Prop = wellTyped {} 43 | 44 | //////////////////////////////////////////////////////////////////////// 45 | // Nat op XXX 46 | //////////////////////////////////////////////////////////////////////// 47 | property("Nat, Nat arguments") = verifyNEqNum[leftNat,rightNat] 48 | property("Nat, Int arguments") = verifyNEqNum[leftNat,rightInt] 49 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 50 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 51 | //////////////////////////////////////////////////////////////////////// 52 | 53 | //////////////////////////////////////////////////////////////////////// 54 | // Char op XXX 55 | //////////////////////////////////////////////////////////////////////// 56 | property("Char, Char arguments") = verifyChar[leftChar,rightChar] 57 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 58 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 59 | //////////////////////////////////////////////////////////////////////// 60 | 61 | //////////////////////////////////////////////////////////////////////// 62 | // Int op XXX 63 | //////////////////////////////////////////////////////////////////////// 64 | property("Int, Nat arguments") = verifyNEqNum[leftInt,rightNat] 65 | property("Int, Int arguments") = verifyNEqNum[leftInt,rightInt] 66 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 67 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 68 | //////////////////////////////////////////////////////////////////////// 69 | 70 | //////////////////////////////////////////////////////////////////////// 71 | // Long op XXX 72 | //////////////////////////////////////////////////////////////////////// 73 | property("Long, Long arguments") = verifyNEqNum[leftLong,rightLong] 74 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 75 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 76 | //////////////////////////////////////////////////////////////////////// 77 | 78 | //////////////////////////////////////////////////////////////////////// 79 | // Float op XXX 80 | //////////////////////////////////////////////////////////////////////// 81 | property("Float, Float arguments") = verifyNEqNum[leftFloat,rightFloat] 82 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 83 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 84 | //////////////////////////////////////////////////////////////////////// 85 | 86 | //////////////////////////////////////////////////////////////////////// 87 | // Double op XXX 88 | //////////////////////////////////////////////////////////////////////// 89 | property("Double, Double arguments") = verifyNEqNum[leftDouble,rightDouble] 90 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 91 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 92 | //////////////////////////////////////////////////////////////////////// 93 | 94 | //////////////////////////////////////////////////////////////////////// 95 | // String op XXX 96 | //////////////////////////////////////////////////////////////////////// 97 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 98 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 99 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 100 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 101 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 102 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 103 | property("String, String arguments") = { 104 | verifyOp2Args[OP,leftString,leftString,False] 105 | verifyOp2Args[OP,leftString,rightString,True] 106 | } 107 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 108 | //////////////////////////////////////////////////////////////////////// 109 | 110 | //////////////////////////////////////////////////////////////////////// 111 | // Boolean op XXX 112 | //////////////////////////////////////////////////////////////////////// 113 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 114 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 115 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 116 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 117 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 118 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 119 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 120 | //////////////////////////////////////////////////////////////////////// 121 | } 122 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/NegateSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | import shapeless.test.illTyped 6 | 7 | class NegateSpec extends Properties("Negate") { 8 | property("Nat argument") = wellTyped { 9 | implicitly[Require[Negate[shapeless.Nat._1] == W.`(-1)`.T]] 10 | } 11 | 12 | property("Char argument") = wellTyped { 13 | implicitly[Require[Negate[W.`'T'`.T] == W.`(-84)`.T]] 14 | } 15 | 16 | property("Int argument") = wellTyped { 17 | implicitly[Require[Negate[W.`2`.T] == W.`(-2)`.T]] 18 | implicitly[Require[Negate[W.`-2`.T] == W.`2`.T]] 19 | } 20 | 21 | property("Long argument") = wellTyped { 22 | implicitly[Require[Negate[W.`5L`.T] == W.`(-5L)`.T]] 23 | implicitly[Require[Negate[W.`-5L`.T] == W.`5L`.T]] 24 | } 25 | 26 | property("Float argument") = wellTyped { 27 | implicitly[Require[Negate[W.`1.5f`.T] == W.`(-1.5f)`.T]] 28 | implicitly[Require[Negate[W.`-1.5f`.T] == W.`1.5f`.T]] 29 | } 30 | 31 | property("Double argument") = wellTyped { 32 | implicitly[Require[Negate[W.`1.5`.T] == W.`(-1.5)`.T]] 33 | implicitly[Require[Negate[W.`-1.5`.T] == W.`1.5`.T]] 34 | } 35 | 36 | property("Boolean argument") = { 37 | illTyped("""implicitly[Negate[W.`true`.T]]""") 38 | true 39 | } 40 | 41 | property("String argument") = { 42 | illTyped("""implicitly[Negate[W.`"Something"`.T]]""") 43 | true 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/OrSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class OrSpec extends Properties("||") { 7 | property("truth table") = wellTyped { 8 | implicitly[Require[(True || True) == True]] 9 | implicitly[Require[(True || False) == True]] 10 | implicitly[Require[(False || True) == True]] 11 | implicitly[Require[(False || False) == False]] 12 | } 13 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/PlusSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class PlusSpec extends Properties("+") { 8 | type OP[L,R] = +[L,R] 9 | type leftNat = shapeless.Nat._1 10 | type leftChar = W.`'\u0001'`.T 11 | type leftInt = W.`1`.T 12 | type leftLong = W.`1L`.T 13 | type leftFloat = W.`1.0f`.T 14 | type leftDouble = W.`1.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._2 19 | type rightChar = W.`'\u0002'`.T 20 | type rightInt = W.`2`.T 21 | type rightLong = W.`2L`.T 22 | type rightFloat = W.`2.0f`.T 23 | type rightDouble = W.`2.0`.T 24 | type rightString = W.`"Else"`.T 25 | type rightBoolean = False 26 | 27 | type resultChar = W.`'\u0003'`.T 28 | type resultInt = W.`3`.T 29 | type resultLong = W.`3L`.T 30 | type resultFloat = W.`3.0f`.T 31 | type resultDouble = W.`3.0`.T 32 | type resultString = W.`"SomethingElse"`.T 33 | type resultBoolean = W.`false`.T 34 | 35 | //////////////////////////////////////////////////////////////////////// 36 | // Nat op XXX 37 | //////////////////////////////////////////////////////////////////////// 38 | property("Nat, Nat arguments") = verifyOp2Args[OP,leftNat,rightNat,resultInt] 39 | property("Nat, Int arguments") = verifyOp2Args[OP,leftNat,rightInt,resultInt] 40 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 41 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 42 | //////////////////////////////////////////////////////////////////////// 43 | 44 | //////////////////////////////////////////////////////////////////////// 45 | // Char op XXX 46 | //////////////////////////////////////////////////////////////////////// 47 | property("Char, Char arguments") = verifyOp2Args[OP,leftChar,rightChar,resultInt] 48 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 49 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 50 | //////////////////////////////////////////////////////////////////////// 51 | 52 | //////////////////////////////////////////////////////////////////////// 53 | // Int op XXX 54 | //////////////////////////////////////////////////////////////////////// 55 | property("Int, Nat arguments") = verifyOp2Args[OP,leftInt,rightNat,resultInt] 56 | property("Int, Int arguments") = verifyOp2Args[OP,leftInt,rightInt,resultInt] 57 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 58 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 59 | //////////////////////////////////////////////////////////////////////// 60 | 61 | //////////////////////////////////////////////////////////////////////// 62 | // Long op XXX 63 | //////////////////////////////////////////////////////////////////////// 64 | property("Long, Long arguments") = verifyOp2Args[OP,leftLong,rightLong,resultLong] 65 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 66 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 67 | //////////////////////////////////////////////////////////////////////// 68 | 69 | //////////////////////////////////////////////////////////////////////// 70 | // Float op XXX 71 | //////////////////////////////////////////////////////////////////////// 72 | property("Float, Float arguments") = verifyOp2Args[OP,leftFloat,rightFloat,resultFloat] 73 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 74 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 75 | //////////////////////////////////////////////////////////////////////// 76 | 77 | //////////////////////////////////////////////////////////////////////// 78 | // Double op XXX 79 | //////////////////////////////////////////////////////////////////////// 80 | property("Double, Double arguments") = verifyOp2Args[OP,leftDouble,rightDouble,resultDouble] 81 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 82 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 83 | //////////////////////////////////////////////////////////////////////// 84 | 85 | //////////////////////////////////////////////////////////////////////// 86 | // String op XXX 87 | //////////////////////////////////////////////////////////////////////// 88 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 89 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 90 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 91 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 92 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 93 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 94 | property("String, String arguments") = verifyOp2Args[OP,leftString,rightString,resultString] 95 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 96 | //////////////////////////////////////////////////////////////////////// 97 | 98 | //////////////////////////////////////////////////////////////////////// 99 | // Boolean op XXX 100 | //////////////////////////////////////////////////////////////////////// 101 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 102 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 103 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 104 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 105 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 106 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 107 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 108 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 109 | //////////////////////////////////////////////////////////////////////// 110 | } 111 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/RequireSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class RequireSpec extends Properties("Require") { 8 | val Testing123 = W("Testing 123") 9 | type Testing123 = Testing123.T 10 | 11 | property("True requirement") = wellTyped { 12 | implicitly[Require[True]] 13 | } 14 | property("False requirement") = wellTyped { 15 | illTyped("""implicitly[Require[False]]""") 16 | } 17 | property("False requirement with message") = wellTyped { 18 | illTyped("""implicitly[RequireMsg[False,Testing123]]""","Testing 123") 19 | } 20 | property("False requirement with message redirected to different symbol") = wellTyped { 21 | @scala.annotation.implicitNotFound("Will be replaced") 22 | trait TestRequireMsg 23 | object TestRequireMsg { 24 | implicit def ev(implicit r : RequireMsg[False, Testing123]) : 25 | TestRequireMsg = new TestRequireMsg {} 26 | } 27 | illTyped("""implicitly[TestRequireMsg]""","Testing 123") 28 | 29 | @scala.annotation.implicitNotFound("Not replaced") 30 | trait TestRequireMsgSymNotReplaced 31 | object TestRequireMsgSymNotReplaced { 32 | implicit def ev(implicit r : RequireMsgSym[False,Testing123,_]) : 33 | TestRequireMsgSymNotReplaced = new TestRequireMsgSymNotReplaced {} 34 | } 35 | illTyped("""implicitly[TestRequireMsgSymNotReplaced]""","Not replaced") 36 | 37 | @scala.annotation.implicitNotFound("Will be replaced") 38 | trait TestRequireMsgSym 39 | object TestRequireMsgSym { 40 | implicit def ev(implicit r : RequireMsgSym[False,Testing123,TestRequireMsgSym]) : 41 | TestRequireMsgSym = new TestRequireMsgSym {} 42 | } 43 | illTyped("""implicitly[TestRequireMsgSym]""","Testing 123") 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/ReverseSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import singleton.TestUtils._ 5 | 6 | class ReverseSpec extends Properties("Reverse") { 7 | property("abc.reverse == cba") = wellTyped { 8 | def reverse[P1 <: XString](implicit op : Reverse[P1]) : op.Out{} = op.value 9 | val r : W.`"cba"`.T = reverse[W.`"abc"`.T] 10 | } 11 | 12 | property("abc.reverse.reverse == abc") = wellTyped { 13 | def reverse[P1 <: XString](implicit op : Reverse[Reverse[P1]]) : op.Out{} = op.value 14 | val r : W.`"abc"`.T = reverse[W.`"abc"`.T] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/STESpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.{Prop, Properties} 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class STESpec extends Properties("<=") { 8 | type OP[L,R] = <=[L,R] 9 | type leftNat = shapeless.Nat._1 10 | type leftChar = W.`'\u0001'`.T 11 | type leftInt = W.`1`.T 12 | type leftLong = W.`1L`.T 13 | type leftFloat = W.`1.0f`.T 14 | type leftDouble = W.`1.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._2 19 | type rightChar = W.`'\u0002'`.T 20 | type rightInt = W.`2`.T 21 | type rightLong = W.`2L`.T 22 | type rightFloat = W.`2.0f`.T 23 | type rightDouble = W.`2.0`.T 24 | type rightString = W.`"Else"`.T 25 | type rightBoolean = False 26 | 27 | def verifySTENum[L,R](implicit 28 | verifyFalse: Verify[R <= L, False], 29 | verifyTrue: Verify[L <= L, True], 30 | verifyTrue2: Verify[L <= R, True]) : Prop = wellTyped {} 31 | 32 | //////////////////////////////////////////////////////////////////////// 33 | // Nat op XXX 34 | //////////////////////////////////////////////////////////////////////// 35 | property("Nat, Nat arguments") = verifySTENum[leftNat,rightNat] 36 | property("Nat, Int arguments") = verifySTENum[leftNat,rightInt] 37 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 38 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 39 | //////////////////////////////////////////////////////////////////////// 40 | 41 | //////////////////////////////////////////////////////////////////////// 42 | // Char op XXX 43 | //////////////////////////////////////////////////////////////////////// 44 | property("Char, Char arguments") = verifySTENum[leftChar,rightChar] 45 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 46 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 47 | //////////////////////////////////////////////////////////////////////// 48 | 49 | //////////////////////////////////////////////////////////////////////// 50 | // Int op XXX 51 | //////////////////////////////////////////////////////////////////////// 52 | property("Int, Nat arguments") = verifySTENum[leftInt,rightNat] 53 | property("Int, Int arguments") = verifySTENum[leftInt,rightInt] 54 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 55 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 56 | //////////////////////////////////////////////////////////////////////// 57 | 58 | //////////////////////////////////////////////////////////////////////// 59 | // Long op XXX 60 | //////////////////////////////////////////////////////////////////////// 61 | property("Long, Long arguments") = verifySTENum[leftLong,rightLong] 62 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 63 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 64 | //////////////////////////////////////////////////////////////////////// 65 | 66 | //////////////////////////////////////////////////////////////////////// 67 | // Float op XXX 68 | //////////////////////////////////////////////////////////////////////// 69 | property("Float, Float arguments") = verifySTENum[leftFloat,rightFloat] 70 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 71 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 72 | //////////////////////////////////////////////////////////////////////// 73 | 74 | //////////////////////////////////////////////////////////////////////// 75 | // Double op XXX 76 | //////////////////////////////////////////////////////////////////////// 77 | property("Double, Double arguments") = verifySTENum[leftDouble,rightDouble] 78 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 79 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 80 | //////////////////////////////////////////////////////////////////////// 81 | 82 | //////////////////////////////////////////////////////////////////////// 83 | // String op XXX 84 | //////////////////////////////////////////////////////////////////////// 85 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 86 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 87 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 88 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 89 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 90 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 91 | property("String, String arguments") = {illTyped("""implicitly[OP[leftString,rightString]]"""); true} 92 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 93 | //////////////////////////////////////////////////////////////////////// 94 | 95 | //////////////////////////////////////////////////////////////////////// 96 | // Boolean op XXX 97 | //////////////////////////////////////////////////////////////////////// 98 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 99 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 100 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 101 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 102 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 103 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 104 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 105 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 106 | //////////////////////////////////////////////////////////////////////// 107 | } 108 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/STSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.{Prop, Properties} 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class STSpec extends Properties("<") { 8 | type OP[L,R] = <[L,R] 9 | type leftNat = shapeless.Nat._1 10 | type leftChar = W.`'\u0001'`.T 11 | type leftInt = W.`1`.T 12 | type leftLong = W.`1L`.T 13 | type leftFloat = W.`1.0f`.T 14 | type leftDouble = W.`1.0`.T 15 | type leftString = W.`"Something"`.T 16 | type leftBoolean = True 17 | 18 | type rightNat = shapeless.Nat._2 19 | type rightChar = W.`'\u0002'`.T 20 | type rightInt = W.`2`.T 21 | type rightLong = W.`2L`.T 22 | type rightFloat = W.`2.0f`.T 23 | type rightDouble = W.`2.0`.T 24 | type rightString = W.`"Else"`.T 25 | type rightBoolean = False 26 | 27 | def verifySTNum[L,R](implicit 28 | verifyFalse: Verify[R < L, False], 29 | verifyFalse2: Verify[L < L, False], 30 | verifyTrue: Verify[L < R, True]) : Prop = wellTyped {} 31 | 32 | //////////////////////////////////////////////////////////////////////// 33 | // Nat op XXX 34 | //////////////////////////////////////////////////////////////////////// 35 | property("Nat, Nat arguments") = verifySTNum[leftNat,rightNat] 36 | property("Nat, Int arguments") = verifySTNum[leftNat,rightInt] 37 | property("Nat, String arguments") = {illTyped("""implicitly[OP[leftNat,rightString]]"""); true} 38 | property("Nat, Boolean arguments") = {illTyped("""implicitly[OP[leftNat,rightBoolean]]"""); true} 39 | //////////////////////////////////////////////////////////////////////// 40 | 41 | //////////////////////////////////////////////////////////////////////// 42 | // Char op XXX 43 | //////////////////////////////////////////////////////////////////////// 44 | property("Char, Char arguments") = verifySTNum[leftChar,rightChar] 45 | property("Char, String arguments") = {illTyped("""implicitly[OP[leftChar,rightString]]"""); true} 46 | property("Char, Boolean arguments") = {illTyped("""implicitly[OP[leftChar,rightBoolean]]"""); true} 47 | //////////////////////////////////////////////////////////////////////// 48 | 49 | //////////////////////////////////////////////////////////////////////// 50 | // Int op XXX 51 | //////////////////////////////////////////////////////////////////////// 52 | property("Int, Nat arguments") = verifySTNum[leftInt,rightNat] 53 | property("Int, Int arguments") = verifySTNum[leftInt,rightInt] 54 | property("Int, String arguments") = {illTyped("""implicitly[OP[leftInt,rightString]]"""); true} 55 | property("Int, Boolean arguments") = {illTyped("""implicitly[OP[leftInt,rightBoolean]]"""); true} 56 | //////////////////////////////////////////////////////////////////////// 57 | 58 | //////////////////////////////////////////////////////////////////////// 59 | // Long op XXX 60 | //////////////////////////////////////////////////////////////////////// 61 | property("Long, Long arguments") = verifySTNum[leftLong,rightLong] 62 | property("Long, String arguments") = {illTyped("""implicitly[OP[leftLong,rightString]]"""); true} 63 | property("Long, Boolean arguments") = {illTyped("""implicitly[OP[leftLong,rightBoolean]]"""); true} 64 | //////////////////////////////////////////////////////////////////////// 65 | 66 | //////////////////////////////////////////////////////////////////////// 67 | // Float op XXX 68 | //////////////////////////////////////////////////////////////////////// 69 | property("Float, Float arguments") = verifySTNum[leftFloat,rightFloat] 70 | property("Float, String arguments") = {illTyped("""implicitly[OP[leftFloat,rightString]]"""); true} 71 | property("Float, Boolean arguments") = {illTyped("""implicitly[OP[leftFloat,rightBoolean]]"""); true} 72 | //////////////////////////////////////////////////////////////////////// 73 | 74 | //////////////////////////////////////////////////////////////////////// 75 | // Double op XXX 76 | //////////////////////////////////////////////////////////////////////// 77 | property("Double, Double arguments") = verifySTNum[leftDouble,rightDouble] 78 | property("Double, String arguments") = {illTyped("""implicitly[OP[leftDouble,rightString]]"""); true} 79 | property("Double, Boolean arguments") = {illTyped("""implicitly[OP[leftDouble,rightBoolean]]"""); true} 80 | //////////////////////////////////////////////////////////////////////// 81 | 82 | //////////////////////////////////////////////////////////////////////// 83 | // String op XXX 84 | //////////////////////////////////////////////////////////////////////// 85 | property("String, Nat arguments") = {illTyped("""implicitly[OP[leftString,rightNat]]"""); true} 86 | property("String, Char arguments") = {illTyped("""implicitly[OP[leftString,rightChar]]"""); true} 87 | property("String, Int arguments") = {illTyped("""implicitly[OP[leftString,rightInt]]"""); true} 88 | property("String, Long arguments") = {illTyped("""implicitly[OP[leftString,rightLong]]"""); true} 89 | property("String, Float arguments") = {illTyped("""implicitly[OP[leftString,rightFloat]]"""); true} 90 | property("String, Double arguments") = {illTyped("""implicitly[OP[leftString,rightDouble]]"""); true} 91 | property("String, String arguments") = {illTyped("""implicitly[OP[leftString,rightString]]"""); true} 92 | property("String, Boolean arguments") = {illTyped("""implicitly[OP[leftString,rightBoolean]]"""); true} 93 | //////////////////////////////////////////////////////////////////////// 94 | 95 | //////////////////////////////////////////////////////////////////////// 96 | // Boolean op XXX 97 | //////////////////////////////////////////////////////////////////////// 98 | property("Boolean, Nat arguments") = {illTyped("""implicitly[OP[leftBoolean,rightNat]]"""); true} 99 | property("Boolean, Char arguments") = {illTyped("""implicitly[OP[leftBoolean,rightChar]]"""); true} 100 | property("Boolean, Int arguments") = {illTyped("""implicitly[OP[leftBoolean,rightInt]]"""); true} 101 | property("Boolean, Long arguments") = {illTyped("""implicitly[OP[leftBoolean,rightLong]]"""); true} 102 | property("Boolean, Float arguments") = {illTyped("""implicitly[OP[leftBoolean,rightFloat]]"""); true} 103 | property("Boolean, Double arguments") = {illTyped("""implicitly[OP[leftBoolean,rightDouble]]"""); true} 104 | property("Boolean, String arguments") = {illTyped("""implicitly[OP[leftBoolean,rightString]]"""); true} 105 | property("Boolean, Boolean arguments") = {illTyped("""implicitly[OP[leftBoolean,rightBoolean]]"""); true} 106 | //////////////////////////////////////////////////////////////////////// 107 | } 108 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/StringOpsSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class StringOpsSpec extends Properties("StringOps") { 8 | property("Substring[foobar, 3] == bar") = wellTyped { 9 | def f[S <: XString, I <: XInt](implicit op : Substring[S, I]) : op.Out{} = op.value 10 | val r : W.`"bar"`.T = f[W.`"foobar"`.T, W.`3`.T] 11 | } 12 | property("Substring abort") = wellTyped {illTyped("""implicitly[Substring[W.`"abc"`.T, W.`4`.T]]""")} 13 | property("Substring unsupported") = wellTyped {illTyped("""implicitly[Substring[W.`true`.T, W.`2`.T]]""")} 14 | 15 | property("SubSequence[foobar, 1, 4] == oob") = wellTyped { 16 | def f[S <: XString, B <: XInt, E <: XInt](implicit op : SubSequence[S, B, E]) : op.Out{} = op.value 17 | val r : W.`"oob"`.T = f[W.`"foobar"`.T, W.`1`.T, W.`4`.T] 18 | } 19 | property("SubSequence abort") = wellTyped {illTyped("""implicitly[SubSequence[W.`"abc"`.T, W.`5`.T, W.`7`.T]]""")} 20 | property("SubSequence unsupported") = wellTyped {illTyped("""implicitly[SubSequence[W.`true`.T, W.`2`.T, W.`3`.T]]""")} 21 | 22 | property("StartsWith[foobar, foo] == true") = wellTyped { 23 | def f[S <: XString, Pre <: XString](implicit op : StartsWith[S, Pre]) : op.Out{} = op.value 24 | val r : W.`true`.T = f[W.`"foobar"`.T, W.`"foo"`.T] 25 | } 26 | property("StartsWith unsupported") = wellTyped {illTyped("""implicitly[StartsWith[W.`"foobar"`.T, W.`true`.T]]""")} 27 | 28 | property("EndsWith[foobar, bar] == true") = wellTyped { 29 | def f[S <: XString, Suf <: XString](implicit op : EndsWith[S, Suf]) : op.Out{} = op.value 30 | val r : W.`true`.T = f[W.`"foobar"`.T, W.`"bar"`.T] 31 | } 32 | property("EndsWith unsupported") = wellTyped {illTyped("""implicitly[EndsWith[W.`"foobar"`.T, W.`true`.T]]""")} 33 | 34 | property("Head[foobar] == f") = wellTyped { 35 | def f[S <: XString](implicit op : Head[S]) : op.Out{} = op.value 36 | val r : W.`'f'`.T = f[W.`"foobar"`.T] 37 | } 38 | property("Head abort") = wellTyped {illTyped("""implicitly[Head[W.`""`.T]]""")} 39 | property("Head unsupported") = wellTyped {illTyped("""implicitly[Head[W.`0`.T]]""")} 40 | 41 | property("Tail[foobar] == oobar") = wellTyped { 42 | def f[S <: XString](implicit op : Tail[S]) : op.Out{} = op.value 43 | val r : W.`"oobar"`.T = f[W.`"foobar"`.T] 44 | } 45 | property("Tail unsupported") = wellTyped {illTyped("""implicitly[Tail[W.`0`.T]]""")} 46 | 47 | property("CharAt[foobar, 3] == b") = wellTyped { 48 | def f[S <: XString, I <: XInt](implicit op : CharAt[S, I]) : op.Out{} = op.value 49 | val r : W.`'b'`.T = f[W.`"foobar"`.T, W.`3`.T] 50 | } 51 | property("CharAt abort") = wellTyped {illTyped("""implicitly[CharAt[W.`"abc"`.T, W.`5`.T]]""")} 52 | property("CharAt unsupported") = wellTyped {illTyped("""implicitly[CharAt[W.`true`.T, W.`2`.T]]""")} 53 | 54 | property("Length[foobar] == 6") = wellTyped { 55 | def f[S <: XString](implicit op : Length[S]) : op.Out{} = op.value 56 | val r : W.`6`.T = f[W.`"foobar"`.T] 57 | } 58 | property("Length unsupported") = wellTyped {illTyped("""implicitly[Length[W.`true`.T]]""")} 59 | 60 | property("Matches[foobar, fo+.*] == true") = wellTyped { 61 | def f[S <: XString, Regex <: XString](implicit op : Matches[S, Regex]) : op.Out{} = op.value 62 | val r : W.`true`.T = f[W.`"foobar"`.T, W.`"fo+.*"`.T] 63 | } 64 | property("Matches abort") = wellTyped {illTyped("""implicitly[Matches[W.`"abc"`.T, W.`"[a"`.T]]""")} 65 | property("Matches unsupported") = wellTyped {illTyped("""implicitly[Matches[W.`"foobar"`.T, W.`true`.T]]""")} 66 | 67 | property("FirstMatch[foobar, b[ar]+] == bar") = wellTyped { 68 | def f[S <: XString, Regex <: XString](implicit op : FirstMatch[S, Regex]) : op.Out{} = op.value 69 | val r : W.`"bar"`.T = f[W.`"foobar"`.T, W.`"b[ar]+"`.T] 70 | } 71 | property("FirstMatch abort") = wellTyped {illTyped("""implicitly[FirstMatch[W.`"abc"`.T, W.`"[a"`.T]]""")} 72 | property("FirstMatch unsupported") = wellTyped {illTyped("""implicitly[FirstMatch[W.`0`.T, W.`".*"`.T]]""")} 73 | 74 | property("PrefixMatch[foobar, fo+] == foo") = wellTyped { 75 | def f[S <: XString, Regex <: XString](implicit op : PrefixMatch[S, Regex]) : op.Out{} = op.value 76 | val r : W.`"foo"`.T = f[W.`"foobar"`.T, W.`"fo+"`.T] 77 | } 78 | property("PrefixMatch abort") = wellTyped {illTyped("""implicitly[PrefixMatch[W.`"abc"`.T, W.`"[a"`.T]]""")} 79 | property("PrefixMatch unsupported") = wellTyped {illTyped("""implicitly[PrefixMatch[W.`true`.T, W.`".*"`.T]]""")} 80 | 81 | property("ReplaceFirstMatch[foobar, [oa], z] == fzobar") = wellTyped { 82 | def f[S <: XString, Regex <: XString, R <: XString](implicit op : ReplaceFirstMatch[S, Regex, R]) : op.Out{} = op.value 83 | val r : W.`"fzobar"`.T = f[W.`"foobar"`.T, W.`"[oa]"`.T, W.`"z"`.T] 84 | } 85 | property("ReplaceFirstMatch abort") = wellTyped {illTyped("""implicitly[ReplaceFirstMatch[W.`"abc"`.T, W.`"[a"`.T, W.`"z"`.T]]""")} 86 | property("ReplaceFirstMatch unsupported") = wellTyped {illTyped("""implicitly[ReplaceFirstMatch[W.`0`.T, W.`".*"`.T, W.`"z"`.T]]""")} 87 | 88 | property("ReplaceAllMatches[foobar, [oa], z] == fzzbzr") = wellTyped { 89 | def f[S <: XString, Regex <: XString, R <: XString](implicit op : ReplaceAllMatches[S, Regex, R]) : op.Out{} = op.value 90 | val r : W.`"fzzbzr"`.T = f[W.`"foobar"`.T, W.`"[oa]"`.T, W.`"z"`.T] 91 | } 92 | property("ReplaceAllMatches abort") = wellTyped {illTyped("""implicitly[ReplaceAllMatches[W.`"abc"`.T, W.`"[a"`.T, W.`"z"`.T]]""")} 93 | property("ReplaceAllMatches unsupported") = wellTyped {illTyped("""implicitly[ReplaceAllMatches[W.`0`.T, W.`".*"`.T, W.`"z"`.T]]""")} 94 | } 95 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/ToConversionSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | 7 | class ToConversionSpec extends Properties("ToConversion") { 8 | property("Nat to Nat") = wellTyped { 9 | def getNat(implicit op : SafeNat[ToNat[shapeless.Nat._1]]) : op.Out = op.value 10 | val ret : shapeless.nat._1 = getNat 11 | } 12 | property("Char to Nat") = wellTyped { 13 | def getNat(implicit op : SafeNat[ToNat[W.`'\u0001'`.T]]) : op.Out = op.value 14 | val ret : shapeless.nat._1 = getNat 15 | } 16 | property("Int to Nat") = wellTyped { 17 | def getNat(implicit op : SafeNat[ToNat[W.`1`.T]]) : op.Out = op.value 18 | val ret : shapeless.nat._1 = getNat 19 | } 20 | property("Long to Nat") = wellTyped { 21 | def getNat(implicit op : SafeNat[ToNat[W.`1L`.T]]) : op.Out = op.value 22 | val ret : shapeless.nat._1 = getNat 23 | } 24 | property("Float to Nat") = wellTyped { 25 | def getNat(implicit op : SafeNat[ToNat[W.`1.0f`.T]]) : op.Out = op.value 26 | val ret : shapeless.nat._1 = getNat 27 | } 28 | property("Double to Nat") = wellTyped { 29 | def getNat(implicit op : SafeNat[ToNat[W.`1.0`.T]]) : op.Out = op.value 30 | val ret : shapeless.nat._1 = getNat 31 | } 32 | 33 | property("Nat to Char") = verifyOp1Args[ToChar,shapeless.Nat._1,W.`'\u0001'`.T] 34 | property("Char to Char") = verifyOp1Args[ToChar,W.`'\u0002'`.T,W.`'\u0002'`.T] 35 | property("Int to Char") = verifyOp1Args[ToChar,W.`3`.T,W.`'\u0003'`.T] 36 | property("Long to Char") = verifyOp1Args[ToChar,W.`4L`.T,W.`'\u0004'`.T] 37 | property("Float to Char") = verifyOp1Args[ToChar,W.`5.0f`.T,W.`'\u0005'`.T] 38 | property("Double to Char") = verifyOp1Args[ToChar,W.`6.0`.T,W.`'\u0006'`.T] 39 | property("String to Char") = {illTyped("""implicitly[ToChar[W.`"7"`.T]]"""); true} 40 | property("Boolean to Char") = {illTyped("""implicitly[ToChar[True]]"""); true} 41 | 42 | property("Nat to Int") = verifyOp1Args[ToInt,shapeless.Nat._1,W.`1`.T] 43 | property("Char to Int") = verifyOp1Args[ToInt,W.`'\u0002'`.T,W.`2`.T] 44 | property("Int to Int") = verifyOp1Args[ToInt,W.`3`.T,W.`3`.T] 45 | property("Long to Int") = verifyOp1Args[ToInt,W.`4L`.T,W.`4`.T] 46 | property("Float to Int") = verifyOp1Args[ToInt,W.`5.0f`.T,W.`5`.T] 47 | property("Double to Int") = verifyOp1Args[ToInt,W.`6.0`.T,W.`6`.T] 48 | property("String to Int") = verifyOp1Args[ToInt,W.`"7"`.T,W.`7`.T] 49 | property("Boolean to Int") = {illTyped("""implicitly[ToInt[True]]"""); true} 50 | 51 | property("Nat to Long") = verifyOp1Args[ToLong,shapeless.Nat._1,W.`1L`.T] 52 | property("Char to Long") = verifyOp1Args[ToLong,W.`'\u0002'`.T,W.`2L`.T] 53 | property("Int to Long") = verifyOp1Args[ToLong,W.`3`.T,W.`3L`.T] 54 | property("Long to Long") = verifyOp1Args[ToLong,W.`4L`.T,W.`4L`.T] 55 | property("Float to Long") = verifyOp1Args[ToLong,W.`5.0f`.T,W.`5L`.T] 56 | property("Double to Long") = verifyOp1Args[ToLong,W.`6.0`.T,W.`6L`.T] 57 | property("String to Long") = verifyOp1Args[ToLong,W.`"7"`.T,W.`7L`.T] 58 | property("Boolean to Long") = {illTyped("""implicitly[ToLong[True]]"""); true} 59 | 60 | property("Nat to Float") = verifyOp1Args[ToFloat,shapeless.Nat._1,W.`1.0f`.T] 61 | property("Char to Float") = verifyOp1Args[ToFloat,W.`'\u0002'`.T,W.`2.0f`.T] 62 | property("Int to Float") = verifyOp1Args[ToFloat,W.`3`.T,W.`3.0f`.T] 63 | property("Long to Float") = verifyOp1Args[ToFloat,W.`4L`.T,W.`4.0f`.T] 64 | property("Float to Float") = verifyOp1Args[ToFloat,W.`5.0f`.T,W.`5.0f`.T] 65 | property("Double to Float") = verifyOp1Args[ToFloat,W.`6.0`.T,W.`6.0f`.T] 66 | property("String to Float") = verifyOp1Args[ToFloat,W.`"7"`.T,W.`7.0f`.T] 67 | property("Boolean to Float") = {illTyped("""implicitly[ToFloat[True]]"""); true} 68 | 69 | property("Nat to Double") = verifyOp1Args[ToDouble,shapeless.Nat._1,W.`1.0`.T] 70 | property("Char to Double") = verifyOp1Args[ToDouble,W.`'\u0002'`.T,W.`2.0`.T] 71 | property("Int to Double") = verifyOp1Args[ToDouble,W.`3`.T,W.`3.0`.T] 72 | property("Long to Double") = verifyOp1Args[ToDouble,W.`4L`.T,W.`4.0`.T] 73 | property("Float to Double") = verifyOp1Args[ToDouble,W.`5.0f`.T,W.`5.0`.T] 74 | property("Double to Double") = verifyOp1Args[ToDouble,W.`6.0`.T,W.`6.0`.T] 75 | property("String to Double") = verifyOp1Args[ToDouble,W.`"7"`.T,W.`7.0`.T] 76 | property("Boolean to Double") = {illTyped("""implicitly[ToDouble[True]]"""); true} 77 | 78 | property("Nat to String") = verifyOp1Args[ToString,shapeless.Nat._1,W.`"1"`.T] 79 | property("Char to String") = verifyOp1Args[ToString,W.`'2'`.T,W.`"2"`.T] 80 | property("Int to String") = verifyOp1Args[ToString,W.`3`.T,W.`"3"`.T] 81 | property("Long to String") = verifyOp1Args[ToString,W.`4L`.T,W.`"4"`.T] 82 | property("Float to String") = verifyOp1Args[ToString,W.`5.0f`.T,W.`"5.0"`.T] 83 | property("Double to String") = verifyOp1Args[ToString,W.`6.0`.T,W.`"6.0"`.T] 84 | property("String to String") = verifyOp1Args[ToString,W.`"7"`.T,W.`"7"`.T] 85 | property("Boolean to String") = verifyOp1Args[ToString,True,W.`"true"`.T] 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/test/scala/singleton/ops/UnsupportedSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.ops 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops.math._ 7 | 8 | //Unsupported operation check to increase coverage 9 | class UnsupportedSpec extends Properties("UnsupportedSpec") { 10 | property("ToNat") = wellTyped {illTyped("""implicitly[ToNat[W.`true`.T]]""")} 11 | property("ToNat with negative number") = wellTyped {illTyped("""implicitly[ToNat[W.`-1`.T]]""","Nat cannot be a negative literal. Found: -1")} 12 | property("ToChar") = wellTyped {illTyped("""implicitly[ToChar[W.`true`.T]]""")} 13 | property("ToInt") = wellTyped {illTyped("""implicitly[ToInt[W.`true`.T]]""")} 14 | property("ToLong") = wellTyped {illTyped("""implicitly[ToLong[W.`true`.T]]""")} 15 | property("ToFloat") = wellTyped {illTyped("""implicitly[ToFloat[W.`true`.T]]""")} 16 | property("ToDouble") = wellTyped {illTyped("""implicitly[ToDouble[W.`true`.T]]""")} 17 | property("Negate") = wellTyped {illTyped("""implicitly[Negate[W.`true`.T]]""")} 18 | property("Abs") = wellTyped {illTyped("""implicitly[Abs[W.`true`.T]]""")} 19 | property("ToDouble") = wellTyped {illTyped("""implicitly[ToDouble[W.`true`.T]]""")} 20 | property("NumberOfLeadingZeros") = wellTyped {illTyped("""implicitly[NumberOfLeadingZeros[W.`true`.T]]""")} 21 | property("Floor") = wellTyped {illTyped("""implicitly[Floor[W.`true`.T]]""")} 22 | property("Ceil") = wellTyped {illTyped("""implicitly[Ceil[W.`true`.T]]""")} 23 | property("Round") = wellTyped {illTyped("""implicitly[Round[W.`true`.T]]""")} 24 | property("Sin") = wellTyped {illTyped("""implicitly[Sin[W.`true`.T]]""")} 25 | property("Cos") = wellTyped {illTyped("""implicitly[Cos[W.`true`.T]]""")} 26 | property("Tan") = wellTyped {illTyped("""implicitly[Tan[W.`true`.T]]""")} 27 | property("Sqrt") = wellTyped {illTyped("""implicitly[Sqrt[W.`true`.T]]""")} 28 | property("Log") = wellTyped {illTyped("""implicitly[Log[W.`true`.T]]""")} 29 | property("Log10") = wellTyped {illTyped("""implicitly[Log10[W.`true`.T]]""")} 30 | property("Reverse") = wellTyped {illTyped("""implicitly[Reverse[W.`true`.T]]""")} 31 | property("Not") = wellTyped {illTyped("""implicitly[![W.`"a"`.T]]""")} 32 | property("Require") = wellTyped { 33 | val a = W(true) 34 | illTyped("""implicitly[RequireMsg[W.`false`.T,W.`false`.T]]""") 35 | // illTyped("""implicitly[RequireMsg[a.T,W.`11`.T]]""") 36 | illTyped("""implicitly[RequireMsg[W.`1`.T,W.`false`.T]]""") 37 | } 38 | property("ITE") = wellTyped {illTyped("""implicitly[ITE[W.`1`.T,W.`1`.T,W.`true`.T]]""")} 39 | property("+") = wellTyped {illTyped("""implicitly[W.`true`.T + W.`2`.T]""")} 40 | property("-") = wellTyped {illTyped("""implicitly[W.`"a"`.T - W.`2`.T]""")} 41 | property("*") = wellTyped {illTyped("""implicitly[W.`true`.T * W.`2`.T]""")} 42 | property("/") = wellTyped {illTyped("""implicitly[W.`true`.T / W.`2`.T]""")} 43 | property("%") = wellTyped {illTyped("""implicitly[W.`true`.T % W.`2`.T]""")} 44 | property("<") = wellTyped {illTyped("""implicitly[W.`true`.T < W.`2`.T]""")} 45 | property(">") = wellTyped {illTyped("""implicitly[W.`true`.T > W.`2`.T]""")} 46 | property("<=") = wellTyped {illTyped("""implicitly[W.`true`.T <= W.`2`.T]""")} 47 | property(">=") = wellTyped {illTyped("""implicitly[W.`true`.T >= W.`2`.T]""")} 48 | property("==") = wellTyped {illTyped("""implicitly[W.`true`.T == W.`2`.T]""")} 49 | property("!=") = wellTyped {illTyped("""implicitly[W.`true`.T != W.`2`.T]""")} 50 | property("&&") = wellTyped {illTyped("""implicitly[W.`1`.T && W.`2`.T]""")} 51 | property("||") = wellTyped {illTyped("""implicitly[W.`1`.T || W.`2`.T]""")} 52 | property("BitwiseAnd") = wellTyped {illTyped("""implicitly[W.`1`.T BitwiseAnd W.`true`.T]""")} 53 | property("BitwiseOr") = wellTyped {illTyped("""implicitly[W.`1`.T BitwiseOr W.`true`.T]""")} 54 | property("Pow") = wellTyped {illTyped("""implicitly[Pow[W.`true`.T, W.`2`.T]]""")} 55 | property("Min") = wellTyped {illTyped("""implicitly[Min[W.`true`.T, W.`2`.T]]""")} 56 | property("Max") = wellTyped {illTyped("""implicitly[Max[W.`true`.T, W.`2`.T]]""")} 57 | property("Substring") = wellTyped {illTyped("""implicitly[Substring[W.`true`.T, W.`2`.T]]""")} 58 | property("CharAt") = wellTyped {illTyped("""implicitly[CharAt[W.`true`.T, W.`2`.T]]""")} 59 | property("Length") = wellTyped {illTyped("""implicitly[Length[W.`true`.T]]""")} 60 | property("No Extraction from Bad Num") = wellTyped {illTyped("""implicitly[Id[Int]]""")} 61 | property("No Extraction from Bad TwoFace") = wellTyped {illTyped("""implicitly[TwoFace.Int[Int]]""")} 62 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/twoface/CheckedBooleanSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedBooleanSpec { 9 | object JustTrue extends Checked0Param.Boolean { 10 | type Cond[T] = T 11 | type Msg[T] = W.`"Failed Check"`.T 12 | } 13 | } 14 | 15 | class CheckedBooleanSpec extends Properties("Checked.Boolean") { 16 | import CheckedBooleanSpec._ 17 | 18 | def condTrue[T](t : JustTrue.Checked[T]) : Unit = {t.unsafeCheck()} 19 | 20 | property("Compile-time checks") = wellTyped { 21 | condTrue(true) 22 | condTrue(TwoFace.Boolean(true)) 23 | illTyped("""condTrue(false)""") 24 | illTyped("""condTrue(TwoFace.Boolean(false))""") 25 | } 26 | 27 | property("Run-time checks") = wellTyped { 28 | condTrue(us(true)) 29 | condTrue(TwoFace.Boolean(us(true))) 30 | illRun{condTrue(us(false))} 31 | illRun{condTrue(TwoFace.Boolean(us(false)))} 32 | } 33 | 34 | def condTrueImpl[T](realValue : Boolean)(implicit t : JustTrue.CheckedShell[T]) : Unit = {t.unsafeCheck(realValue)} 35 | 36 | property("Shell compile-time checks") = wellTyped { 37 | condTrueImpl[True](true) 38 | illTyped("""condTrueImpl[False](true)""", "Failed Check") 39 | illTyped("""condTrueImpl[False](false)""", "Failed Check") 40 | } 41 | 42 | property("Shell run-time checks") = wellTyped { 43 | condTrueImpl[Boolean](true) 44 | illRun{condTrueImpl[Boolean](false)} 45 | } 46 | 47 | trait CheckedUse[T] 48 | object CheckedUse { 49 | implicit def ev[T](implicit checkedTrue: JustTrue.CheckedShellSym[CheckedUse[_], T]) : CheckedUse[T] = 50 | new CheckedUse[T] {} 51 | } 52 | 53 | property("Shell user message redirect checks") = wellTyped { 54 | implicitly[CheckedUse[True]] 55 | illTyped("""implicitly[CheckedUse[False]]""", "Failed Check") 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/scala/singleton/twoface/CheckedCharSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedCharSpec { 9 | object SmallerThan50 extends Checked0Param.Char { 10 | type Cond[T] = T < W.`'\u0032'`.T 11 | type Msg[T] = W.`"Failed Check"`.T 12 | } 13 | } 14 | 15 | class CheckedCharSpec extends Properties("Checked.Char") { 16 | import CheckedCharSpec._ 17 | 18 | def smallerThan50[T](t : SmallerThan50.Checked[T]) : Unit = {t.unsafeCheck()} 19 | 20 | property("Compile-time checks") = wellTyped { 21 | smallerThan50('\u0020') 22 | smallerThan50(TwoFace.Char('\u0020')) 23 | illTyped("""smallerThan50('\u0032')""") 24 | illTyped("""smallerThan50(TwoFace.Char('\u0032'))""") 25 | } 26 | 27 | property("Run-time checks") = wellTyped { 28 | smallerThan50(us('\u0020')) 29 | smallerThan50(TwoFace.Char(us('\u0020'))) 30 | illRun{smallerThan50(us('\u0032'))} 31 | illRun{smallerThan50(TwoFace.Char(us('\u0032')))} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/scala/singleton/twoface/CheckedDoubleSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedDoubleSpec { 9 | object SmallerThan50 extends Checked0Param.Double { 10 | type Cond[T] = T < W.`50.0`.T 11 | type Msg[T] = W.`"Failed Check"`.T 12 | } 13 | } 14 | 15 | class CheckedDoubleSpec extends Properties("Checked.Double") { 16 | import CheckedDoubleSpec._ 17 | 18 | def smallerThan50[T](t : SmallerThan50.Checked[T]) : Unit = {t.unsafeCheck()} 19 | 20 | property("Compile-time checks") = wellTyped { 21 | smallerThan50(40.0) 22 | smallerThan50(TwoFace.Double(40.0)) 23 | illTyped("""smallerThan50(50.0)""") 24 | illTyped("""smallerThan50(TwoFace.Double(50.0))""") 25 | } 26 | 27 | property("Run-time checks") = wellTyped { 28 | smallerThan50(us(40.0)) 29 | smallerThan50(TwoFace.Double(us(40.0))) 30 | illRun{smallerThan50(us(50.0))} 31 | illRun{smallerThan50(TwoFace.Double(us(50.0)))} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/scala/singleton/twoface/CheckedFloatSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedFloatSpec { 9 | object SmallerThan50 extends Checked0Param.Float { 10 | type Cond[T] = T < W.`50.0f`.T 11 | type Msg[T] = W.`"Failed Check"`.T 12 | } 13 | } 14 | 15 | class CheckedFloatSpec extends Properties("Checked.Float") { 16 | import CheckedFloatSpec._ 17 | 18 | def smallerThan50[T](t : SmallerThan50.Checked[T]) : Unit = {t.unsafeCheck()} 19 | 20 | property("Compile-time checks") = wellTyped { 21 | smallerThan50(40.0f) 22 | smallerThan50(TwoFace.Float(40.0f)) 23 | illTyped("""smallerThan50(50.0f)""") 24 | illTyped("""smallerThan50(TwoFace.Float(50.0f))""") 25 | } 26 | 27 | property("Run-time checks") = wellTyped { 28 | smallerThan50(us(40.0f)) 29 | smallerThan50(TwoFace.Float(us(40.0f))) 30 | illRun{smallerThan50(us(50.0f))} 31 | illRun{smallerThan50(TwoFace.Float(us(50.0f)))} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/scala/singleton/twoface/CheckedLongSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedLongSpec { 9 | object SmallerThan50 extends Checked0Param.Long { 10 | type Cond[T] = T < W.`50L`.T 11 | type Msg[T] = W.`"Failed Check"`.T 12 | } 13 | } 14 | 15 | class CheckedLongSpec extends Properties("Checked.Long") { 16 | import CheckedLongSpec._ 17 | 18 | def smallerThan50[T](t : SmallerThan50.Checked[T]) : Unit = {t.unsafeCheck()} 19 | 20 | property("Compile-time checks") = wellTyped { 21 | smallerThan50(40L) 22 | smallerThan50(TwoFace.Long(40L)) 23 | illTyped("""smallerThan50(50L)""") 24 | illTyped("""smallerThan50(TwoFace.Long(50L))""") 25 | } 26 | 27 | property("Run-time checks") = wellTyped { 28 | smallerThan50(us(40L)) 29 | smallerThan50(TwoFace.Long(us(40L))) 30 | illRun{smallerThan50(us(50L))} 31 | illRun{smallerThan50(TwoFace.Long(us(50L)))} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/scala/singleton/twoface/TwoFaceBooleanSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | class TwoFaceBooleanSpec extends Properties("TwoFace.Boolean") { 9 | property("Implicit Creation[]") = { 10 | val a = implicitly[TwoFace.Boolean[W.`true`.T]] 11 | a.getValue && a.isLiteral 12 | } 13 | property("Safe Creation[]") = { 14 | val a = TwoFace.Boolean[W.`true`.T] 15 | a.getValue && a.isLiteral 16 | } 17 | property("Safe Creation()") = { 18 | val a = TwoFace.Boolean(true) 19 | a.getValue && a.isLiteral 20 | } 21 | property("Unsafe Creation()") = { 22 | val a = TwoFace.Boolean(us(true)) 23 | a.getValue && !a.isLiteral 24 | } 25 | property("Safe ifThenElse") = verifyTFBoolean(ifThenElse(true, false, true), false) 26 | property("Unsafe ifThenElse") = verifyTFBoolean(ifThenElse(us(false), false, true), us(true)) 27 | 28 | property("Safe Boolean") = verifyTFBoolean(!TwoFace.Boolean(true), false) 29 | property("!Unsafe Boolean") = verifyTFBoolean(!TwoFace.Boolean(us(false)), us(true)) 30 | 31 | property("Safe Boolean == Regular Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(true) == (true), true) 32 | property("Safe Boolean == Regular Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(false) == (us(false)), us(true)) 33 | property("Unsafe Boolean == Regular Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(true)) == (true), us(true)) 34 | property("Unsafe Boolean == Regular Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) == (us(false)), us(true)) 35 | 36 | property("Safe Boolean != Regular Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(false) != (false), false) 37 | property("Safe Boolean != Regular Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(false) != (us(false)), us(false)) 38 | property("Unsafe Boolean != Regular Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) != (false), us(false)) 39 | property("Unsafe Boolean != Regular Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) != (us(false)), us(false)) 40 | 41 | property("Safe Boolean == Safe Boolean") = { 42 | val result = TwoFace.Boolean(true) == TwoFace.Boolean(true) 43 | implicitly[result.Out =:= W.`true`.T] 44 | result.getValue 45 | } 46 | property("Safe Boolean == Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(false) == TwoFace.Boolean(us(false)), us(true)) 47 | property("Unsafe Boolean == Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(true)) == TwoFace.Boolean(true), us(true)) 48 | property("Unsafe Boolean == Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) == TwoFace.Boolean(us(false)), us(true)) 49 | 50 | property("Safe Boolean != Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(true) != TwoFace.Boolean(true), false) 51 | property("Safe Boolean != Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(false) != TwoFace.Boolean(us(false)), us(false)) 52 | property("Unsafe Boolean != Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(true)) != TwoFace.Boolean(true), us(false)) 53 | property("Unsafe Boolean != Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) != TwoFace.Boolean(us(false)), us(false)) 54 | 55 | property("Safe Boolean && Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(true) && TwoFace.Boolean(true), true) 56 | property("Safe Boolean (true) && Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(true) && TwoFace.Boolean(us(true)), us(true)) 57 | property("Safe Boolean (false) && Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(false) && TwoFace.Boolean(us(true)), false) 58 | property("Unsafe Boolean && Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) && TwoFace.Boolean(true), us(false)) 59 | property("Unsafe Boolean && Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) && TwoFace.Boolean(us(false)), us(false)) 60 | 61 | property("Safe Boolean || Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(true) || TwoFace.Boolean(true), true) 62 | property("Safe Boolean (true) || Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(true) || TwoFace.Boolean(us(true)), true) 63 | property("Safe Boolean (false) || Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(false) || TwoFace.Boolean(us(true)), us(true)) 64 | property("Unsafe Boolean || Safe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) || TwoFace.Boolean(true), us(true)) 65 | property("Unsafe Boolean || Unsafe Boolean") = verifyTFBoolean(TwoFace.Boolean(us(false)) || TwoFace.Boolean(us(false)), us(false)) 66 | 67 | property("Safe toStringTF") = verifyTFString(TwoFace.Boolean(true).toStringTF, "true") 68 | property("Unsafe toStringTF") = verifyTFString(TwoFace.Boolean(us(false)).toStringTF, us("false")) 69 | 70 | property("Safe require") = wellTyped { 71 | require(TwoFace.Boolean(true), "something") 72 | illTyped("""require(TwoFace.Boolean(false), "something")""","something") 73 | illRun(require(TwoFace.Boolean(us(false)), us("something"))) 74 | } 75 | property("Unsafe require") = wellTyped { 76 | require(TwoFace.Boolean(us(true)), "something") 77 | illRun(require(TwoFace.Boolean(us(false)), "something")) 78 | } 79 | 80 | property("Implicit Conversions") = wellTyped { 81 | val a : TwoFace.Boolean[W.`true`.T] = implicitly[TwoFace.Boolean[W.`true`.T || W.`false`.T]] 82 | val b : TwoFace.Boolean[W.`true`.T || W.`false`.T] = implicitly[TwoFace.Boolean[W.`true`.T && W.`true`.T]] 83 | val c : TwoFace.Boolean[W.`true`.T && W.`true`.T] = implicitly[TwoFace.Boolean[W.`true`.T]] 84 | val d : W.`true`.T = TwoFace.Boolean(true) 85 | val e : Boolean = TwoFace.Boolean(us(false)) 86 | val f : TwoFace.Boolean[Boolean] = false 87 | } 88 | 89 | property("Wrong Implicit Conversions") = wellTyped { 90 | illTyped("""val impl = implicitly[TwoFace.Boolean[W.`false`.T && W.`true`.T]]; val a : TwoFace.Boolean[W.`true`.T] = impl""") 91 | illTyped("""val impl = implicitly[TwoFace.Boolean[W.`true`.T]]; val b : TwoFace.Boolean[W.`false`.T && W.`true`.T] = impl""") 92 | } 93 | 94 | property("ToString") = { 95 | TwoFace.Boolean[W.`true`.T].toString() == "true" 96 | } 97 | 98 | type Fin = W.`true`.T 99 | final val fin = true 100 | 101 | property("Extracting from an Upper Bounded Numeric") = wellTyped { 102 | def foo[W](width: TwoFace.Boolean[W]) = width 103 | def foo2[R <: Boolean](r: R) = foo(r) 104 | val a = foo2(W(fin).value) 105 | implicitly[a.Out =:= Fin] 106 | val b = foo2(us(fin)) 107 | implicitly[b.Out =:= Boolean] 108 | } 109 | 110 | property("Extracting from Safe TwoFace") = { 111 | val a = me(TwoFace.Boolean(fin)) 112 | val ret = shapeless.the[Id[a.T]] 113 | implicitly[ret.Out =:= Fin] 114 | ret.value == fin 115 | } 116 | 117 | def noImplFoo[W](w : TwoFace.Boolean[W]) = !w //Missing twoface shell implicit 118 | property("Unavailable Implicit Safe TwoFace Shell") = { 119 | val ret = noImplFoo(true) 120 | implicitly[ret.Out <:< ![W.`true`.T]] 121 | val retSimple = ret.simplify 122 | implicitly[retSimple.Out <:< W.`false`.T] 123 | retSimple.getValue == false 124 | } 125 | property("Unavailable Implicit Unsafe TwoFace Shell") = { 126 | val ret = noImplFoo(us(true)) 127 | implicitly[ret.Out <:< ![Boolean]] 128 | val retSimple = ret.simplify 129 | implicitly[retSimple.Out <:< Boolean] 130 | retSimple.getValue == false 131 | } 132 | } -------------------------------------------------------------------------------- /src/test/scala/singleton/twoface/TwoFaceStringSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | class TwoFaceStringSpec extends Properties("TwoFace.String") { 9 | property("Implicit Creation[]") = { 10 | val a = implicitly[TwoFace.String[W.`"Something"`.T]] 11 | a.getValue == "Something" && a.isLiteral 12 | } 13 | property("Safe Creation[]") = { 14 | val a = TwoFace.String[W.`"Something"`.T] 15 | a.getValue == "Something" && a.isLiteral 16 | } 17 | property("Safe Creation()") = { 18 | val a = TwoFace.String("Something") 19 | a.getValue == "Something" && a.isLiteral 20 | } 21 | property("Unsafe Creation()") = { 22 | val a = TwoFace.String(us("Something")) 23 | a.getValue == "Something" && !a.isLiteral 24 | } 25 | 26 | property("Safe ifThenElse") = verifyTFString(ifThenElse(true, "Hi", "Hello"), "Hi") 27 | property("Unsafe ifThenElse") = verifyTFString(ifThenElse(us(false), "Hi", "Hello"), us("Hello")) 28 | 29 | property("Safe String + Safe String") = verifyTFString(TwoFace.String("Some") + TwoFace.String("thing"), "Something") 30 | property("Safe String + Unsafe String") = verifyTFString(TwoFace.String("Some") + TwoFace.String(us("thing")), us("Something")) 31 | property("Unsafe String + Safe String") = verifyTFString(TwoFace.String(us("Some")) + TwoFace.String("thing"), us("Something")) 32 | property("Unsafe String + Unsafe String") = verifyTFString(TwoFace.String(us("Some")) + TwoFace.String(us("thing")), us("Something")) 33 | 34 | property("Safe String == Regular Safe String") = { 35 | val result = TwoFace.String("Some") == TwoFace.String("Some") 36 | implicitly[result.Out =:= W.`true`.T] 37 | result.getValue 38 | } 39 | property("Safe String == Regular Unsafe String") = verifyTFBoolean(TwoFace.String("Some") == (us("Some")), us(true)) 40 | property("Unsafe String == Regular Safe String") = verifyTFBoolean(TwoFace.String(us("Some")) == ("Some"), us(true)) 41 | property("Unsafe String == Regular Unsafe String") = verifyTFBoolean(TwoFace.String(us("Some")) == (us("Some")), us(true)) 42 | 43 | property("Safe String != Regular Safe String") = verifyTFBoolean(TwoFace.String("Some") != ("Some"), false) 44 | property("Safe String != Regular Unsafe String") = verifyTFBoolean(TwoFace.String("Some") != (us("Some")), us(false)) 45 | property("Unsafe String != Regular Safe String") = verifyTFBoolean(TwoFace.String(us("Some")) != ("Some"), us(false)) 46 | property("Unsafe String != Regular Unsafe String") = verifyTFBoolean(TwoFace.String(us("Some")) != (us("Some")), us(false)) 47 | 48 | property("Safe String substring Safe Int") = verifyTFString(TwoFace.String("Something") substring TwoFace.Int(4), "thing") 49 | property("Safe String substring Unsafe Int") = verifyTFString(TwoFace.String("Something") substring TwoFace.Int(us(4)), us("thing")) 50 | property("Unsafe String substring Safe Int") = verifyTFString(TwoFace.String(us("Something")) substring TwoFace.Int(4), us("thing")) 51 | property("Unsafe String substring Unsafe Int") = verifyTFString(TwoFace.String(us("Something")) substring TwoFace.Int(us(4)), us("thing")) 52 | 53 | property("Safe String charAt Safe Int") = verifyTFChar(TwoFace.String("Something") charAt TwoFace.Int(4), 't') 54 | property("Safe String charAt Unsafe Int") = verifyTFChar(TwoFace.String("Something") charAt TwoFace.Int(us(4)), us('t')) 55 | property("Unsafe String charAt Safe Int") = verifyTFChar(TwoFace.String(us("Something")) charAt TwoFace.Int(4), us('t')) 56 | property("Unsafe String charAt Unsafe Int") = verifyTFChar(TwoFace.String(us("Something")) charAt TwoFace.Int(us(4)), us('t')) 57 | 58 | property("Safe toNat") = wellTyped { 59 | val nat = TwoFace.String("1").toNat 60 | verifyOp[nat.N, shapeless.Nat._1] 61 | } 62 | property("Safe toInt") = verifyTFInt(TwoFace.String("1").toInt, 1) 63 | property("Unsafe toInt") = verifyTFInt(TwoFace.String(us("1")).toInt, us(1)) 64 | property("Safe toLong") = verifyTFLong(TwoFace.String("1").toLong, 1L) 65 | property("Unsafe toLong") = verifyTFLong(TwoFace.String(us("1")).toLong, us(1L)) 66 | property("Safe toFloat") = verifyTFFloat(TwoFace.String("1.0").toFloat, 1.0f) 67 | property("Unsafe toFloat") = verifyTFFloat(TwoFace.String(us("1.0")).toFloat, us(1.0f)) 68 | property("Safe toDouble") = verifyTFDouble(TwoFace.String("1.0").toDouble, 1.0) 69 | property("Unsafe toDouble") = verifyTFDouble(TwoFace.String(us("1.0")).toDouble, us(1.0)) 70 | 71 | property("Safe length") = verifyTFInt(TwoFace.String("Some").length, 4) 72 | property("Unsafe length") = verifyTFInt(TwoFace.String(us("Some")).length, us(4)) 73 | 74 | property("Safe reverse") = verifyTFString(TwoFace.String("Some").reverse, "emoS") 75 | property("Unsafe reverse") = verifyTFString(TwoFace.String(us("Some")).reverse, us("emoS")) 76 | 77 | property("Implicit Conversions") = wellTyped { 78 | val a : TwoFace.String[W.`"Something"`.T] = implicitly[TwoFace.String[W.`"Some"`.T + W.`"thing"`.T]] 79 | val b : TwoFace.String[W.`"Som"`.T + W.`"ething"`.T] = implicitly[TwoFace.String[W.`"Some"`.T + W.`"thing"`.T]] 80 | val c : TwoFace.String[W.`"Some"`.T + W.`"thing"`.T] = implicitly[TwoFace.String[W.`"Something"`.T]] 81 | val d : W.`"Some"`.T = TwoFace.String("Some") 82 | val e : String = TwoFace.String(us("Some")) 83 | val f : TwoFace.String[String] = "Some" 84 | } 85 | 86 | property("Wrong Implicit Conversions") = wellTyped { 87 | illTyped("""val impl = implicitly[TwoFace.String[W.`"Som"`.T + W.`"E"`.T]]; val a : TwoFace.String[W.`"Some"`.T] = impl""") 88 | illTyped("""val impl = implicitly[TwoFace.String[W.`"SomeThing"`.T]]; val b : TwoFace.String[W.`"Some"`.T + W.`"thing"`.T] = impl""") 89 | } 90 | 91 | type Fin = W.`"a"`.T 92 | final val fin = "a" 93 | 94 | property("Extracting from an Upper Bounded Numeric") = wellTyped { 95 | def foo[W](width: TwoFace.String[W]) = width 96 | def foo2[R <: String](r: R) = foo(r) 97 | val a = foo2(W(fin).value) 98 | implicitly[a.Out =:= Fin] 99 | val b = foo2(us(fin)) 100 | implicitly[b.Out =:= String] 101 | } 102 | 103 | property("Extracting from Safe TwoFace") = { 104 | val a = me(TwoFace.String(fin)) 105 | val ret = shapeless.the[Id[a.T]] 106 | implicitly[ret.Out =:= Fin] 107 | ret.value == fin 108 | } 109 | 110 | def noImplFoo[W](w : TwoFace.String[W]) = w + w //Missing twoface shell implicit 111 | property("Unavailable Implicit Safe TwoFace Shell") = { 112 | val ret = noImplFoo("Ma") 113 | implicitly[ret.Out <:< +[W.`"Ma"`.T,W.`"Ma"`.T]] 114 | val retSimple = ret.simplify 115 | implicitly[retSimple.Out <:< W.`"MaMa"`.T] 116 | retSimple.getValue == "MaMa" 117 | } 118 | property("Unavailable Implicit Unsafe TwoFace Shell") = { 119 | val ret = noImplFoo(us("Ma")) 120 | implicitly[ret.Out <:< +[String, String]] 121 | val retSimple = ret.simplify 122 | implicitly[retSimple.Out <:< String] 123 | retSimple.getValue == "MaMa" 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/test/scala_2.13+/singleton/twoface/CheckedIntSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedIntSpec { 9 | object SmallerThan50 extends Checked0Param.Int { 10 | type Cond[T] = T < W.`50`.T 11 | type Msg[T] = W.`"Failed Check"`.T 12 | } 13 | } 14 | 15 | class CheckedIntSpec extends Properties("Checked.Int") { 16 | import CheckedIntSpec._ 17 | 18 | def foo[T](t : TwoFace.Int[T]) = t 19 | def smallerThan50[T](t : SmallerThan50.Checked[T]) = { 20 | val a : Int = t 21 | foo(t.unsafeCheck()) 22 | } 23 | def smallerThan50Seq(tSeq : SmallerThan50.Checked[Int]*) = { 24 | for (t <- tSeq) { 25 | val a : Int = t 26 | foo(t.unsafeCheck()) 27 | } 28 | } 29 | 30 | property("Compile-time checks") = wellTyped { 31 | implicitly[SmallerThan50.Checked[W.`5`.T]] 32 | val b = implicitly[SmallerThan50.Checked[W.`5`.T + W.`3`.T]] 33 | implicitly[b.Out <:< (W.`5`.T + W.`3`.T)] 34 | val c = smallerThan50(40) 35 | implicitly[c.Out <:< W.`40`.T] 36 | smallerThan50(TwoFace.Int(40)) 37 | smallerThan50(TwoFace.Int[W.`30`.T]) 38 | smallerThan50(implicitly[TwoFace.Int[W.`30`.T]]) 39 | smallerThan50Seq(1,2,3) 40 | val widen : SmallerThan50.Checked[Int] = 5 41 | illTyped("""smallerThan50(50)""" ,"Failed Check") 42 | illTyped("""smallerThan50(TwoFace.Int(50))""", "Failed Check") 43 | illTyped("""implicitly[SmallerThan50.Checked[W.`60`.T]]""", "Failed Check") 44 | illTyped("""val widen2 : SmallerThan50.Checked[Int] = 50""" ,"Failed Check") 45 | illTyped("""smallerThan50Seq(1,us(70),60)""","Failed Check") 46 | } 47 | 48 | property("Run-time checks") = wellTyped { 49 | smallerThan50Seq(1,2,3) 50 | smallerThan50Seq(us(1),2,3) 51 | smallerThan50(us(40)) 52 | smallerThan50(TwoFace.Int(us(40))) 53 | val us70 = 70 54 | val us60 = 60 55 | illRun{smallerThan50(us(50))} 56 | illRun{smallerThan50(TwoFace.Int(us(50)))} 57 | illRun{smallerThan50Seq(1,us70,us60)} 58 | } 59 | 60 | //Maybe at fault of Scalac, but some schemes prove better than others to avoid errors 61 | property("Stability check") = wellTyped { 62 | class Fooish[T] 63 | class Foo { 64 | final def foo : Fooish[W.`4`.T] = new Fooish[W.`4`.T] 65 | final def foo[T](value : SmallerThan50.Checked[T]) : Fooish[value.Out] = new Fooish[value.Out] 66 | } 67 | val a = new Foo 68 | val b : Fooish[W.`2`.T] = a.foo(2) 69 | val two = 2 70 | val c : Fooish[Int] = a.foo(two) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/scala_2.13+/singleton/twoface/CheckedStringSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedStringSpec { 9 | object LengthSmallerThan extends Checked1Param.String { 10 | type Cond[T, P] = Length[T] < P 11 | type Msg[T, P] = W.`"Length of string '"`.T + T + W.`"' is not smaller than "`.T + ToString[P] 12 | type ParamFace = Int 13 | } 14 | } 15 | 16 | class CheckedStringSpec extends Properties("Checked.String") { 17 | import CheckedStringSpec._ 18 | 19 | def foo[T](t : TwoFace.String[T]) : Unit = {} 20 | def lengthSmallerThan5[T](t : LengthSmallerThan.Checked[T,Id[W.`5`.T]]) : Unit = { 21 | val temp : String = t 22 | foo(t.unsafeCheck(5)) 23 | } 24 | def lengthSmallerThan5Seq(tSeq : LengthSmallerThan.Checked[String,W.`5`.T]*) : Unit = { 25 | for (t <- tSeq) { 26 | val temp : String = t 27 | foo(t.unsafeCheck(5)) 28 | } 29 | } 30 | def lengthSmallerThanFive[T](t : LengthSmallerThan.Checked[T, Int]) : Unit = { 31 | val temp : String = t 32 | foo(t.unsafeCheck(5)) 33 | } 34 | def lengthSmallerThanFiveImpl[T](implicit t : LengthSmallerThan.Checked[T, Int]) : Unit = { 35 | val temp : String = t 36 | foo(t.unsafeCheck(5)) 37 | } 38 | 39 | property("Compile-time checks") = wellTyped { 40 | lengthSmallerThan5("Hi") 41 | lengthSmallerThan5(TwoFace.String("Hi")) 42 | implicitly[LengthSmallerThan.Checked[W.`"Hi"`.T,W.`5`.T]] 43 | lengthSmallerThan5Seq("Hi", "Hey") 44 | illTyped("""lengthSmallerThan5("Hello")""","Length of string 'Hello' is not smaller than 5") 45 | illTyped("""lengthSmallerThan5(TwoFace.String("Hello"))""","Length of string 'Hello' is not smaller than 5") 46 | illTyped("""implicitly[LengthSmallerThan.Checked[W.`"Hello"`.T,W.`5`.T]]""","Length of string 'Hello' is not smaller than 5") 47 | illTyped("""lengthSmallerThan5Seq("Hi", "Hey", "Hello")""","Length of string 'Hello' is not smaller than 5") 48 | } 49 | 50 | property("Run-time checks") = wellTyped { 51 | lengthSmallerThan5(us("Hi")) 52 | lengthSmallerThan5(TwoFace.String(us("Hi"))) 53 | lengthSmallerThanFive("Hi") 54 | lengthSmallerThanFive(TwoFace.String("Hi")) 55 | lengthSmallerThan5Seq(us("Hi"), "Hey") 56 | lengthSmallerThanFiveImpl[W.`"Hi"`.T] 57 | illRun{lengthSmallerThan5(us("Hello"))} 58 | illRun{lengthSmallerThan5(TwoFace.String(us("Hello")))} 59 | illRun{lengthSmallerThanFive("Hello")} 60 | illRun{lengthSmallerThanFive(TwoFace.String("Hello"))} 61 | illRun{lengthSmallerThanFiveImpl[W.`"Hello"`.T]} 62 | val usHello = "Hello" 63 | illRun{lengthSmallerThan5Seq(us("Hi"), "Hey", usHello)} 64 | } 65 | 66 | def lengthSmallerThan5Impl[T](realValue : String)(implicit t : LengthSmallerThan.CheckedShell[T,W.`5`.T]) : Unit = 67 | {t.unsafeCheck(realValue, 5)} 68 | 69 | property("Shell compile-time checks") = wellTyped { 70 | lengthSmallerThan5Impl[W.`"Hi"`.T](us("Hi")) 71 | illTyped("""lengthSmallerThan5Impl[W.`"Hello"`.T](us("Hello"))""", "Length of string 'Hello' is not smaller than 5") 72 | } 73 | 74 | property("Shell run-time checks") = wellTyped { 75 | lengthSmallerThan5Impl[String](us("Hi")) 76 | illRun{lengthSmallerThan5Impl[String](us("Hello"))} 77 | } 78 | 79 | trait CheckedUse[T] 80 | object CheckedUse { 81 | implicit def ev[T](implicit checkedTrue: LengthSmallerThan.CheckedShellSym[CheckedUse[_], T, W.`5`.T]) : CheckedUse[T] = 82 | new CheckedUse[T] {} 83 | } 84 | 85 | property("Shell user message redirect checks") = wellTyped { 86 | implicitly[CheckedUse[W.`"Hi"`.T]] 87 | illTyped("""implicitly[CheckedUse[W.`"Hello"`.T]]""", "Length of string 'Hello' is not smaller than 5") 88 | } 89 | 90 | //Maybe at fault of Scalac, but some schemes prove better than others to avoid errors 91 | property("Stability check") = wellTyped { 92 | class Fooish[T] 93 | class Foo { 94 | final def foo : Fooish[W.`"Hello"`.T] = new Fooish[W.`"Hello"`.T] 95 | final def foo[T](value : LengthSmallerThan.Checked[T, W.`10`.T]) : Fooish[value.Out] = new Fooish[value.Out] 96 | } 97 | val a = new Foo 98 | val b : Fooish[W.`"World"`.T] = a.foo("World") 99 | val world = "World" 100 | val c : Fooish[String] = a.foo(world) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/test/scala_2.13-/singleton/twoface/CheckedIntSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedIntSpec { 9 | object SmallerThan50 extends Checked0Param.Int { 10 | type Cond[T] = T < W.`50`.T 11 | type Msg[T] = W.`"Failed Check"`.T 12 | } 13 | } 14 | 15 | class CheckedIntSpec extends Properties("Checked.Int") { 16 | import CheckedIntSpec._ 17 | 18 | def foo[T](t : TwoFace.Int[T]) = t 19 | def smallerThan50[T](t : SmallerThan50.Checked[T]) = { 20 | val a : Int = t 21 | foo(t.unsafeCheck()) 22 | } 23 | def smallerThan50Seq(tSeq : SmallerThan50.Checked[Int]*) = { 24 | for (t <- tSeq) { 25 | val a : Int = t 26 | foo(t.unsafeCheck()) 27 | } 28 | } 29 | 30 | property("Compile-time checks") = wellTyped { 31 | implicitly[SmallerThan50.Checked[W.`5`.T]] 32 | val b = implicitly[SmallerThan50.Checked[W.`5`.T + W.`3`.T]] 33 | implicitly[b.Out <:< (W.`5`.T + W.`3`.T)] 34 | val c = smallerThan50(40) 35 | implicitly[c.Out <:< W.`40`.T] 36 | smallerThan50(TwoFace.Int(40)) 37 | smallerThan50(TwoFace.Int[W.`30`.T]) 38 | smallerThan50(implicitly[TwoFace.Int[W.`30`.T]]) 39 | smallerThan50Seq(1,2,3) 40 | val widen : SmallerThan50.Checked[Int] = 5 41 | illTyped("""smallerThan50(50)""" ,"Failed Check") 42 | illTyped("""smallerThan50(TwoFace.Int(50))""", "Failed Check") 43 | illTyped("""implicitly[SmallerThan50.Checked[W.`60`.T]]""", "Failed Check") 44 | illTyped("""val widen2 : SmallerThan50.Checked[Int] = 50""" ,"Failed Check") 45 | illTyped("""smallerThan50Seq(1,us(70),60)""","Failed Check") 46 | } 47 | 48 | property("Run-time checks") = wellTyped { 49 | smallerThan50Seq(us(1),2,3) 50 | smallerThan50(us(40)) 51 | smallerThan50(TwoFace.Int(us(40))) 52 | val us70 = 70 53 | val us60 = 60 54 | illRun{smallerThan50(us(50))} 55 | illRun{smallerThan50(TwoFace.Int(us(50)))} 56 | illRun{smallerThan50Seq(1,us70,us60)} 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/scala_2.13-/singleton/twoface/CheckedStringSpec.scala: -------------------------------------------------------------------------------- 1 | package singleton.twoface 2 | 3 | import org.scalacheck.Properties 4 | import shapeless.test.illTyped 5 | import singleton.TestUtils._ 6 | import singleton.ops._ 7 | 8 | object CheckedStringSpec { 9 | object LengthSmallerThan extends Checked1Param.String { 10 | type Cond[T, P] = Length[T] < P 11 | type Msg[T, P] = W.`"Length of string '"`.T + T + W.`"' is not smaller than "`.T + ToString[P] 12 | type ParamFace = Int 13 | } 14 | } 15 | 16 | class CheckedStringSpec extends Properties("Checked.String") { 17 | import CheckedStringSpec._ 18 | 19 | def foo[T](t : TwoFace.String[T]) : Unit = {} 20 | def lengthSmallerThan5[T](t : LengthSmallerThan.Checked[T,Id[W.`5`.T]]) : Unit = { 21 | val temp : String = t 22 | foo(t.unsafeCheck(5)) 23 | } 24 | def lengthSmallerThan5Seq(tSeq : LengthSmallerThan.Checked[String,W.`5`.T]*) : Unit = { 25 | for (t <- tSeq) { 26 | val temp : String = t 27 | foo(t.unsafeCheck(5)) 28 | } 29 | } 30 | def lengthSmallerThanFive[T](t : LengthSmallerThan.Checked[T, Int]) : Unit = { 31 | val temp : String = t 32 | foo(t.unsafeCheck(5)) 33 | } 34 | def lengthSmallerThanFiveImpl[T](implicit t : LengthSmallerThan.Checked[T, Int]) : Unit = { 35 | val temp : String = t 36 | foo(t.unsafeCheck(5)) 37 | } 38 | 39 | property("Compile-time checks") = wellTyped { 40 | lengthSmallerThan5("Hi") 41 | lengthSmallerThan5(TwoFace.String("Hi")) 42 | implicitly[LengthSmallerThan.Checked[W.`"Hi"`.T,W.`5`.T]] 43 | lengthSmallerThan5Seq("Hi", "Hey") 44 | illTyped("""lengthSmallerThan5("Hello")""","Length of string 'Hello' is not smaller than 5") 45 | illTyped("""lengthSmallerThan5(TwoFace.String("Hello"))""","Length of string 'Hello' is not smaller than 5") 46 | illTyped("""implicitly[LengthSmallerThan.Checked[W.`"Hello"`.T,W.`5`.T]]""","Length of string 'Hello' is not smaller than 5") 47 | illTyped("""lengthSmallerThan5Seq("Hi", "Hey", "Hello")""","Length of string 'Hello' is not smaller than 5") 48 | } 49 | 50 | property("Run-time checks") = wellTyped { 51 | lengthSmallerThan5(us("Hi")) 52 | lengthSmallerThan5(TwoFace.String(us("Hi"))) 53 | lengthSmallerThanFive("Hi") 54 | lengthSmallerThanFive(TwoFace.String("Hi")) 55 | lengthSmallerThan5Seq(us("Hi"), "Hey") 56 | lengthSmallerThanFiveImpl[W.`"Hi"`.T] 57 | illRun{lengthSmallerThan5(us("Hello"))} 58 | illRun{lengthSmallerThan5(TwoFace.String(us("Hello")))} 59 | illRun{lengthSmallerThanFive("Hello")} 60 | illRun{lengthSmallerThanFive(TwoFace.String("Hello"))} 61 | illRun{lengthSmallerThanFiveImpl[W.`"Hello"`.T]} 62 | val usHello = "Hello" 63 | illRun{lengthSmallerThan5Seq(us("Hi"), "Hey", usHello)} 64 | } 65 | 66 | def lengthSmallerThan5Impl[T](realValue : String)(implicit t : LengthSmallerThan.CheckedShell[T,W.`5`.T]) : Unit = 67 | {t.unsafeCheck(realValue, 5)} 68 | 69 | property("Shell compile-time checks") = wellTyped { 70 | lengthSmallerThan5Impl[W.`"Hi"`.T](us("Hi")) 71 | illTyped("""lengthSmallerThan5Impl[W.`"Hello"`.T](us("Hello"))""", "Length of string 'Hello' is not smaller than 5") 72 | } 73 | 74 | property("Shell run-time checks") = wellTyped { 75 | lengthSmallerThan5Impl[String](us("Hi")) 76 | illRun{lengthSmallerThan5Impl[String](us("Hello"))} 77 | } 78 | 79 | trait CheckedUse[T] 80 | object CheckedUse { 81 | implicit def ev[T](implicit checkedTrue: LengthSmallerThan.CheckedShellSym[CheckedUse[_], T, W.`5`.T]) : CheckedUse[T] = 82 | new CheckedUse[T] {} 83 | } 84 | 85 | property("Shell user message redirect checks") = wellTyped { 86 | implicitly[CheckedUse[W.`"Hi"`.T]] 87 | illTyped("""implicitly[CheckedUse[W.`"Hello"`.T]]""", "Length of string 'Hello' is not smaller than 5") 88 | } 89 | 90 | } 91 | --------------------------------------------------------------------------------