{"id":16680852,"url":"https://github.com/fthomas/singleton-ops","last_synced_at":"2025-04-06T09:11:06.305Z","repository":{"id":41063244,"uuid":"59956642","full_name":"fthomas/singleton-ops","owner":"fthomas","description":"Operations for primitive and String singleton types","archived":false,"fork":false,"pushed_at":"2024-08-12T20:56:33.000Z","size":1298,"stargazers_count":163,"open_issues_count":17,"forks_count":20,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-30T08:08:59.612Z","etag":null,"topics":["scala","singleton-types"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fthomas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-29T17:55:38.000Z","updated_at":"2024-03-18T14:33:52.000Z","dependencies_parsed_at":"2023-02-15T11:45:49.886Z","dependency_job_id":"6c7d5cdd-2079-4841-8540-212c4718edc4","html_url":"https://github.com/fthomas/singleton-ops","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fthomas%2Fsingleton-ops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fthomas%2Fsingleton-ops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fthomas%2Fsingleton-ops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fthomas%2Fsingleton-ops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fthomas","download_url":"https://codeload.github.com/fthomas/singleton-ops/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247457803,"owners_count":20941906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["scala","singleton-types"],"created_at":"2024-10-12T13:44:07.795Z","updated_at":"2025-04-06T09:11:06.281Z","avatar_url":"https://github.com/fthomas.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# singleton-ops\n[![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)\n[![codecov](https://codecov.io/gh/fthomas/singleton-ops/branch/master/graph/badge.svg)](https://codecov.io/gh/fthomas/singleton-ops)\n[![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\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![Scaladex](https://index.scala-lang.org/fthomas/singleton-ops/singleton-ops/latest.svg?color=blue)](https://index.scala-lang.org/fthomas/singleton-ops)\n[![Scala.js](https://www.scala-js.org/assets/badges/scalajs-0.6.17.svg)](https://www.scala-js.org)\n\nThis library provides type-level operations for [Typelevel Scala][typelevel-scala] with [SIP-23][sip-23].\n## Simple example:\n```scala\nimport singleton.ops._\n\nclass MyVec[L] {\n  def doubleSize = new MyVec[2 * L]\n  def nSize[N] = new MyVec[N * L]\n  def getLength(implicit length : SafeInt[L]) : Int = length\n}\nobject MyVec {\n  implicit def apply[L](implicit check : Require[L \u003e 0]) : MyVec[L] = new MyVec[L]()\n}\nval myVec : MyVec[10] = MyVec[4 + 1].doubleSize\nval myBadVec = MyVec[-1] //fails compilation, as required\n```\n\n---\n## Using singleton-ops\n\nThe 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.\n\nIf you're using sbt, add the following to your build:\n\n```sbt\nlibraryDependencies ++= Seq(\n  \"eu.timepit\" %% \"singleton-ops\" % \"0.5.0\"\n)\n```\nIf you're using scala.js use `%%%` instead\n\n```sbt\nlibraryDependencies ++= Seq(\n  \"eu.timepit\" %%% \"singleton-ops\" % \"0.5.0\"\n)\n```\n**Be sure to follow Typelevel Scala [instructions][typelevel-scala-use], to be able to use literal types in your code.**\n\n---\n#### Supported types:\n* `Char with Singleton` (aliased as `XChar`) \n* `Int with Singleton` (aliased as `XInt`) \n* `Long with Singleton` (aliased as `XLong`)\n* `Float with Singleton` (aliased as `XFloat`)\n* `Double with Singleton` (aliased as `XDouble`)\n* `String with Singleton` (aliased as `XString`)\n* `Boolean with Singleton` (aliased as `XBoolean`)\n* `Nat` (from [Shapeless][shapeless])\n\n#### Supported arithmetic operations:\n* `type +[P1, P2]`          \n* `type -[P1, P2]`          \n* `type *[P1, P2]`          \n* `type /[P1, P2]`          \n* `type %[P1, P2]`          \n* `type Abs[P1]`            \n* `type Negate[P1]`         \n\n#### Supported relational operations:\n* `type ==[P1, P2]`         \n* `type !=[P1, P2]`         \n* `type \u003e[P1, P2]`          \n* `type \u003c[P1, P2]`          \n* `type \u003e=[P1, P2]`         \n* `type \u003c=[P1, P2]`         \n* `type Min[P1, P2]`        \n* `type Max[P1, P2]`        \n\n#### Supported logical operations:\n* `type \u0026\u0026[P1, P2]`         \n* `type ||[P1, P2]`         \n* `type ![P1]`              \n\n#### Supported explicit conversion operations:\n* `type ToNat[P1]`          \n* `type ToChar[P1]`          \n* `type ToInt[P1]`          \n* `type ToLong[P1]`         \n* `type ToFloat[P1]`          \n* `type ToDouble[P1]`       \n* `type ToString[P1]`          \n\n#### Supported string operations:\n* `type Length[S]`\n* `type +[S1, S2]` (concat)\n* `type Reverse[S]`\n* `type CharAt[S, I]`\n* `type Substring[S, I]`\n* `type SubSequence[S, IBeg, IEnd]`\n* `type StartsWith[S, Prefix]`\n* `type EndsWith[S, Suffix]`\n* `type Head[S]`\n* `type Tail[S]`\n* `type Matches[S, Regex]`\n* `type FirstMatch[S, Regex]`\n* `type PrefixMatch[S, Regex]`\n* `type ReplaceFirstMatch[S, Regex, R]`\n* `type ReplaceAllMatches[S, Regex, R]`\n\n#### Supported constraints operations:\n* `type Require[P1]`        \n\n#### Supported control operations:\n* `type ==\u003e[A, B]` (`first A then B`)        \n* `type ITE[I,T,E]` (`If (I) Then (T) Else (E)`)      \n\n#### Supported Aux Pattern interface:\n* `type OpAuxNat[O \u003c: Op,      Ret_Out \u003c: Nat]`\n* `type OpAuxChar[O \u003c: Op,     Ret_Out \u003c: XChar]`     \n* `type OpAuxInt[O \u003c: Op,      Ret_Out \u003c: XInt]`      \n* `type OpAuxLong[O \u003c: Op,     Ret_Out \u003c: XLong]`    \n* `type OpAuxFloat[O \u003c: Op,    Ret_Out \u003c: XFloat]`   \n* `type OpAuxDouble[O \u003c: Op,   Ret_Out \u003c: XDouble]`  \n* `type OpAuxString[O \u003c: Op,   Ret_Out \u003c: XString]`  \n* `type OpAuxBoolean[O \u003c: Op,  Ret_Out \u003c: XBoolean]` \n\n\n## Examples\n\n* `Int` type operations:\n```scala\nimport singleton.ops._\ndef demo[L \u003c: XInt](implicit p : L*L + L) : p.Out = p.value\nval b : 30 = demo[5]\n```\n* `Long` type operations:\n```scala\nimport singleton.ops._\ndef demoLong[L1 \u003c: XLong, L2 \u003c: XLong](implicit p : Min[L1*L1, L2+L2]) : p.Out = p.value\nval bLong1 : 1L = demoLong[1L, 5L]\nval bLong2 : 6L = demoLong[3L, 3L]\n```\n\n* `Double` type operations:\n```scala\nimport singleton.ops._\ndef demoDouble[L1 \u003c: XDouble, L2 \u003c: XDouble](implicit p : L1 / L2 + 1.0) : p.Out = p.value\nval bDouble : 1.2 = demoDouble[1.0, 5.0]\n```\n\n* Combined `Long` and `Int` type operations:\n```scala\nimport singleton.ops._\ndef demoSumLongInt[L1 \u003c: XLong, L2 \u003c: XInt](implicit p : L1 + L2) : p.Out = p.value\nval bSumLongInt : 16L = demoSumLongInt[8L, 8]\n```\n\n* `String` type operations:\n```scala\nimport singleton.ops._\ndef demoString[P1 \u003c: XString](implicit op : Reverse[P1] + P1) : op.Out = op.value\nval bString : \"cbaabc\" = demoString[\"abc\"]\n```\n\n* `Boolean` type operations:\n```scala\nimport singleton.ops._\ndef demoBoolean[P1 \u003c: XInt](implicit op : P1 \u003c 0) : op.Out = op.value\nval bBoolean1 : true = demoBoolean[-5]\nval bBoolean2 : false = demoBoolean[5]\nval bBoolean3 : false = demoBoolean[0]\n```\n\n* `Boolean` type constraints:\n```scala\nimport singleton.ops._\ndef demoRequire[P1 \u003c: XInt](implicit op : Require[P1 \u003c 0]) : op.Out = op.value\nscala\u003e demoRequire[-1]\ndemoRequire[-1]\nres0: Boolean(true) = true\nscala\u003e demoRequire[1]\n\u003cconsole\u003e:16: error: could not find implicit Out for parameter op: singleton.ops.Require[singleton.ops.\u003c[1,0]]\n       demoRequire[1]\n```\n\n* Shapeless' `Nat` type operations:\n```scala\nimport singleton.ops._\nimport shapeless._\nval n = Nat(5)\n//Converting Nat to Int singleton occurs implicitly\ndef demoNatToSing[L \u003c: Nat](implicit p : L+L) : p.Out = p.value\nval bSing10 : 10 = demoNatToSing[n.N]\n//Converting Int singleton to Nat requires explicit `ToNat`\ndef demoSingToNat[L \u003c: XInt](implicit op : ToNat[L+L]) : op.Out = op.value\nval bNat10 : shapeless.nat._10 = demoSingToNat[5]\n```\n\n* Working with large numbers doesn't slay the compiler:\n```scala\nimport singleton.ops._\ndef bigMul[L1 \u003c: XLong, L2 \u003c: XLong](implicit p : L1 * L2) : p.Out = p.value\nscala\u003e bigMul[32000L, 6400000L]\nres2: Long = 204800000000\n```\n\n## Contributors and participation\n\n* [Frank S. Thomas](https://github.com/fthomas)\n* [Matthew Pocock](https://github.com/drdozer)\n* [Naoki Aoyama](https://github.com/aoiroaoino)\n* [Oron Port](https://github.com/soronpo)\n* [Carlos Quiroz](https://github.com/cquiroz)\n\nThe singleton-ops project supports the [Typelevel][typelevel]\n[code of conduct][typelevel-coc] and wants all of its channels (Gitter,\nGitHub, etc.) to be welcoming environments for everyone.\n\n[shapeless]: https://github.com/milessabin/shapeless\n[sip-23]: http://docs.scala-lang.org/sips/pending/42.type.html\n[typelevel]: http://typelevel.org/\n[typelevel-coc]: http://typelevel.org/conduct.html\n[typelevel-scala]: https://github.com/typelevel/scala\n[typelevel-scala-use]: https://github.com/typelevel/scala#how-to-use-typelevel-scala-4-with-sbt\n[twoface-discourse]: https://contributors.scala-lang.org/t/twoface-Outs-closing-the-gap-between-run-compile-time-functionality/869\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffthomas%2Fsingleton-ops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffthomas%2Fsingleton-ops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffthomas%2Fsingleton-ops/lists"}