( 後日追記 )
The latest version of the library is 0.9.27, which is available for Scala and Scala.js version 2.12 and 2.13.
( 省略 )
libraryDependencies ++= Seq(
"eu.timepit" %% "refined" % "0.9.27",
"eu.timepit" %% "refined-cats" % "0.9.27", // optional
"eu.timepit" %% "refined-eval" % "0.9.27", // optional, JVM-only
"eu.timepit" %% "refined-jsonpath" % "0.9.27", // optional, JVM-only
"eu.timepit" %% "refined-pureconfig" % "0.9.27", // optional, JVM-only
"eu.timepit" %% "refined-scalacheck" % "0.9.27", // optional
"eu.timepit" %% "refined-scalaz" % "0.9.27", // optional
"eu.timepit" %% "refined-scodec" % "0.9.27", // optional
"eu.timepit" %% "refined-scopt" % "0.9.27", // optional
"eu.timepit" %% "refined-shapeless" % "0.9.27" // optional
)
上の記載に従って、__build.sbtファイルを次のように記載して、sbt.consoleを実行したところ、refined__の読み込みとREPL環境の起動に成功した。
scalaVersion := "2.13.6"
libraryDependencies += "eu.timepit" %% "refined" % "0.9.27"
diy@electronnoMacBook-Pro refined_trial %
cat build.sbt
scalaVersion := "2.13.6"
libraryDependencies += "eu.timepit" %% "refined" % "0.9.27"
diy@electronnoMacBook-Pro refined_trial %
diy@electronnoMacBook-Pro refined_trial % sbt console
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by sbt.TrapExit$ (file:/Users/electron/.sbt/boot/scala-2.12.14/org.scala-sbt/sbt/1.5.5/run_2.12-1.5.5.jar)
WARNING: Please consider reporting this to the maintainers of sbt.TrapExit$
WARNING: System::setSecurityManager will be removed in a future release
[info] welcome to sbt 1.5.5 (Homebrew Java 17.0.1)
[info] loading project definition from /Users/electron/scala_trial/refined_trial/project
[info] loading settings for project refined_trial from build.sbt ...
[info] set current project to refined_trial (in build file:/Users/electron/scala_trial/refined_trial/)
[info] Updating
https://repo1.maven.org/maven2/eu/timepit/refined_2.13/0.9.27/refined_2.13-0.9.27.pom
100.0% [##########] 2.6 KiB (1.7 KiB / s)
https://repo1.maven.org/maven2/org/scala-lang/modules/scala-xml_2.13/1.3.0/scala-xml_2.13-1.3.0.pom
100.0% [##########] 2.8 KiB (9.3 KiB / s)
https://repo1.maven.org/maven2/com/chuusai/shapeless_2.13/2.3.7/shapeless_2.13-2.3.7.pom
100.0% [##########] 2.3 KiB (3.6 KiB / s)
[info] Resolved dependencies
[info] Fetching artifacts of
https://repo1.maven.org/maven2/eu/timepit/refined_2.13/0.9.27/refined_2.13-0.9.27.jar
100.0% [##########] 594.8 KiB (709.7 KiB / s)
https://repo1.maven.org/maven2/org/scala-lang/modules/scala-xml_2.13/1.3.0/scala-xml_2.13-1.3.0.jar
100.0% [##########] 558.1 KiB (583.2 KiB / s)
https://repo1.maven.org/maven2/com/chuusai/shapeless_2.13/2.3.7/shapeless_2.13-2.3.7.jar
100.0% [##########] 3.1 MiB (2.4 MiB / s)
[info] Fetched artifacts of
[info] Starting scala interpreter...
Welcome to Scala 2.13.6 (OpenJDK 64-Bit Server VM, Java 17.0.1).
Type in expressions for evaluation. Or try :help.
scala>
scala> import eu.timepit.refined._
import eu.timepit.refined._
scala> import eu.timepit.refined.auto._
import eu.timepit.refined.auto._
scala> import eu.timepit.refined.numeric._
import eu.timepit.refined.numeric._
scala> import eu.timepit.refined.api.{RefType, Refined}
import eu.timepit.refined.api.{RefType, Refined}
scala> import eu.timepit.refined.boolean._
import eu.timepit.refined.boolean._
scala> import eu.timepit.refined.char._
|
import eu.timepit.refined.char._
scala> import eu.timepit.refined.collection._
import eu.timepit.refined.collection._
scala> import eu.timepit.refined.generic._
import eu.timepit.refined.generic._
scala> import eu.timepit.refined.string._
import eu.timepit.refined.string._
scala> import shapeless.{ ::, HNil }
import shapeless.{$colon$colon, HNil}
scala>
scala> refineMV[NonEmpty]("Hello")
val res0: eu.timepit.refined.api.Refined[String,eu.timepit.refined.collection.NonEmpty] = Hello
scala> refineMV[NonEmpty]("")
scala> type ZeroToOne = Not[Less[0.0]] And Not[Greater[1.0]]
type ZeroToOne
scala> refineMV[AnyOf[Digit :: Letter :: Whitespace :: HNil]]('F')
val res4: eu.timepit.refined.api.Refined[Char,eu.timepit.refined.boolean.AnyOf[eu.timepit.refined.char.Digit :: eu.timepit.refined.char.Letter :: eu.timepit.refined.char.Whitespace :: shapeless.HNil]] = F
scala> val d1: Char Refined Equal['3'] = '3'
val d1: eu.timepit.refined.api.Refined[Char,eu.timepit.refined.generic.Equal['3']] = 3
scala> val d2: Char Refined Digit = d1
val d2: eu.timepit.refined.api.Refined[Char,eu.timepit.refined.char.Digit] = 3
scala> type Age = Int Refined Interval.ClosedOpen[7, 77]
type Age
scala> val userInput = 55
val userInput: Int = 55
scala> val ageEither1: Either[String, Age] = refineV(userInput)
val ageEither1: Either[String,Age] = Right(55)
scala> val ageEither2 = RefType.applyRef[Age](userInput)
val ageEither2: Either[String,Age] = Right(55)
scala> :q
[success] Total time: 208 s (03:28), completed 2021/11/08 1:08:28
diy@electronnoMacBook-Pro refined_trial %
__type__で型に別名をつける方法は、以下が参考になります。
なお、__refined__で定義されている型制約条件の述語(predicate)については、公式ドキュメント(以下)を参照ください。
build.sbtファイルをこう書くと、sbt.consoleは起動できた
- build.sbtファイルの記述内容
scalaVersion := "2.13.6"
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2"
( 参考 )
build.sbt を開き、以下の行を追加します。 libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2"
sbt consoleは正常に起動する
diy@electronnoMacBook-Pro refined_trial % sbt console
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by sbt.TrapExit$ (file:/Users/diy/.sbt/boot/scala-2.12.14/org.scala-sbt/sbt/1.5.5/run_2.12-1.5.5.jar)
WARNING: Please consider reporting this to the maintainers of sbt.TrapExit$
WARNING: System::setSecurityManager will be removed in a future release
[info] welcome to sbt 1.5.5 (Homebrew Java 17.0.1)
[info] loading project definition from /Users/diy/scala_trial/refined_trial/project
[info] loading settings for project refined_trial from build.sbt ...
[info] set current project to refined_trial (in build file:/Users/diy/scala_trial/refined_trial/)
[info] Updating
https://repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.13.6/scala-compiler-2.13.6.pom
100.0% [##########] 2.3 KiB (2.8 KiB / s)
https://repo1.maven.org/maven2/org/jline/jline/3.19.0/jline-3.19.0.pom
100.0% [##########] 17.2 KiB (108.7 KiB / s)
https://repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.13.6/scala-reflect-2.13.6.pom
100.0% [##########] 1.8 KiB (5.0 KiB / s)
[info] Resolved dependencies
[info] Fetching artifacts of
https://repo1.maven.org/maven2/org/jline/jline/3.19.0/jline-3.19.0.jar
100.0% [##########] 963.9 KiB (1.2 MiB / s)
https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.6/scala-library-2.13.6.jar
100.0% [##########] 5.7 MiB (4.3 MiB / s)
https://repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.13.6/scala-reflect-2.13.6.jar
100.0% [##########] 3.6 MiB (2.5 MiB / s)
https://repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.13.6/scala-compiler-2.13.6.jar
100.0% [##########] 11.5 MiB (6.0 MiB / s)
[info] Fetched artifacts of
[info] Non-compiled module 'compiler-bridge_2.13' for Scala 2.13.6. Compiling...
[info] Compilation completed in 8.089s.
[info] Starting scala interpreter...
Welcome to Scala 2.13.6 (OpenJDK 64-Bit Server VM, Java 17.0.1).
Type in expressions for evaluation. Or try :help.
scala>
scala> 1 + 1
val res0: Int = 2
scala> println(1 + 1)
2
scala> :q
[success] Total time: 30 s, completed 2021/11/07 19:15:29
diy@electronnoMacBook-Pro refined_trial %
Refinedライブラリを読み込むように、build.sbtを修正
- 複数のライブラリを追加する場合の書き方
今後複数のライブラリを使用する場合に、一度に定義することも可能です。
以下のように記述します。libraryDependenciesに対して+=ではなく++=を使うことによってSeqの形で一度に複数のライブラリを追加することができます。
build.sbt libraryDependencies ++= Seq( "org.apache.commons" % "commons-text" % "1.8", ... )
Refinedライブラリを読み込むように追記
( 参考 )
まずRefinedを依存ライブラリに追加します。 libraryDependencies ++= Seq( "eu.timepit" %% "refined" % "0.8.4", )
修正後のbuild.sbtファイル
scalaVersion := "2.13.6"
libraryDependencies ++= Seq(
"org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2",
"eu.timepit" %% "refined" % "0.8.4",
)
エラー(not found)
Refinedのダウンロード先が見つからないというエラーが吐かれた。
Terminal[error] sbt.librarymanagement.ResolveException: Error downloading eu.timepit:refined_2.13:0.9.0 [error] Not found
diy@electronnoMacBook-Pro refined_trial % sbt console
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by sbt.TrapExit$ (file:/Users/diy/.sbt/boot/scala-2.12.14/org.scala-sbt/sbt/1.5.5/run_2.12-1.5.5.jar)
WARNING: Please consider reporting this to the maintainers of sbt.TrapExit$
WARNING: System::setSecurityManager will be removed in a future release
[info] welcome to sbt 1.5.5 (Homebrew Java 17.0.1)
[info] loading project definition from /Users/diy/scala_trial/refined_trial/project
[info] loading settings for project refined_trial from build.sbt ...
[info] set current project to refined_trial (in build file:/Users/diy/scala_trial/refined_trial/)
[info] Updating
[info] Resolved dependencies
[warn]
[warn] Note: Unresolved dependencies path:
[error] sbt.librarymanagement.ResolveException: Error downloading eu.timepit:refined_2.13:0.9.0
[error] Not found
[error] Not found
[error] not found: /Users/diy/.ivy2/localeu.timepit/refined_2.13/0.9.0/ivys/ivy.xml
[error] not found: https://repo1.maven.org/maven2/eu/timepit/refined_2.13/0.9.0/refined_2.13-0.9.0.pom
[error] at lmcoursier.CoursierDependencyResolution.unresolvedWarningOrThrow(CoursierDependencyResolution.scala:258)
[error] at lmcoursier.CoursierDependencyResolution.$anonfun$update$38(CoursierDependencyResolution.scala:227)
[error] at scala.util.Either$LeftProjection.map(Either.scala:573)
[error] at lmcoursier.CoursierDependencyResolution.update(CoursierDependencyResolution.scala:227)
[error] at sbt.librarymanagement.DependencyResolution.update(DependencyResolution.scala:60)
[error] at sbt.internal.LibraryManagement$.resolve$1(LibraryManagement.scala:59)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$12(LibraryManagement.scala:133)
[error] at sbt.util.Tracked$.$anonfun$lastOutput$1(Tracked.scala:73)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$20(LibraryManagement.scala:146)
[error] at scala.util.control.Exception$Catch.apply(Exception.scala:228)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11(LibraryManagement.scala:146)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11$adapted(LibraryManagement.scala:127)
[error] at sbt.util.Tracked$.$anonfun$inputChangedW$1(Tracked.scala:219)
[error] at sbt.internal.LibraryManagement$.cachedUpdate(LibraryManagement.scala:160)
[error] at sbt.Classpaths$.$anonfun$updateTask0$1(Defaults.scala:3678)
[error] at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error] at sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error] at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] at sbt.Execute.work(Execute.scala:291)
[error] at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[error] at java.base/java.lang.Thread.run(Thread.java:833)
[error] (update) sbt.librarymanagement.ResolveException: Error downloading eu.timepit:refined_2.13:0.9.0
[error] Not found
[error] Not found
[error] not found: /Users/diy/.ivy2/localeu.timepit/refined_2.13/0.9.0/ivys/ivy.xml
[error] not found: https://repo1.maven.org/maven2/eu/timepit/refined_2.13/0.9.0/refined_2.13-0.9.0.pom
[error] Total time: 1 s, completed 2021/11/07 19:29:22
diy@electronnoMacBook-Pro refined_trial %
diy@electronnoMacBook-Pro refined_trial % scala
Welcome to Scala 2.13.6 (OpenJDK 64-Bit Server VM, Java 17.0.1).
Type in expressions for evaluation. Or try :help.
scala> import eu.timepit.refined._
^
error: not found: value eu
scala> :q
diy@electronnoMacBook-Pro refined_trial %
これもエラー
- build.sbtファイルの記述内容
scalaVersion := "2.13.6"
libraryDependencies ++= Seq(
"eu.timepit" %% "refined" % "0.9.0",
)
( 参考 )
###導入
build.sbtのライブラリ依存性に以下のように追加します。
libraryDependencies ++= Seq( "eu.timepit" %% "refined" % "0.9.0", )
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by sbt.TrapExit$ (file:/Users/diy/.sbt/boot/scala-2.12.14/org.scala-sbt/sbt/1.5.5/run_2.12-1.5.5.jar)
WARNING: Please consider reporting this to the maintainers of sbt.TrapExit$
WARNING: System::setSecurityManager will be removed in a future release
[info] welcome to sbt 1.5.5 (Homebrew Java 17.0.1)
[info] loading project definition from /Users/diy/scala_trial/refined_trial/project
[info] loading settings for project refined_trial from build.sbt ...
[info] set current project to refined_trial (in build file:/Users/diy/scala_trial/refined_trial/)
[info] Updating
[info] Resolved dependencies
[warn]
[warn] Note: Unresolved dependencies path:
[error] sbt.librarymanagement.ResolveException: Error downloading eu.timepit:refined_2.13:0.9.0
[error] Not found
[error] Not found
[error] not found: /Users/diy/.ivy2/localeu.timepit/refined_2.13/0.9.0/ivys/ivy.xml
[error] not found: https://repo1.maven.org/maven2/eu/timepit/refined_2.13/0.9.0/refined_2.13-0.9.0.pom
[error] at lmcoursier.CoursierDependencyResolution.unresolvedWarningOrThrow(CoursierDependencyResolution.scala:258)
[error] at lmcoursier.CoursierDependencyResolution.$anonfun$update$38(CoursierDependencyResolution.scala:227)
[error] at scala.util.Either$LeftProjection.map(Either.scala:573)
[error] at lmcoursier.CoursierDependencyResolution.update(CoursierDependencyResolution.scala:227)
[error] at sbt.librarymanagement.DependencyResolution.update(DependencyResolution.scala:60)
[error] at sbt.internal.LibraryManagement$.resolve$1(LibraryManagement.scala:59)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$12(LibraryManagement.scala:133)
[error] at sbt.util.Tracked$.$anonfun$lastOutput$1(Tracked.scala:73)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$20(LibraryManagement.scala:146)
[error] at scala.util.control.Exception$Catch.apply(Exception.scala:228)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11(LibraryManagement.scala:146)
[error] at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11$adapted(LibraryManagement.scala:127)
[error] at sbt.util.Tracked$.$anonfun$inputChangedW$1(Tracked.scala:219)
[error] at sbt.internal.LibraryManagement$.cachedUpdate(LibraryManagement.scala:160)
[error] at sbt.Classpaths$.$anonfun$updateTask0$1(Defaults.scala:3678)
[error] at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error] at sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error] at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] at sbt.Execute.work(Execute.scala:291)
[error] at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[error] at java.base/java.lang.Thread.run(Thread.java:833)
[error] (update) sbt.librarymanagement.ResolveException: Error downloading eu.timepit:refined_2.13:0.9.0
[error] Not found
[error] Not found
[error] not found: /Users/diy/.ivy2/localeu.timepit/refined_2.13/0.9.0/ivys/ivy.xml
[error] not found: https://repo1.maven.org/maven2/eu/timepit/refined_2.13/0.9.0/refined_2.13-0.9.0.pom
[error] Total time: 1 s, completed 2021/11/07 19:33:30
( その他参考 )
今回は、Scalaの非同期HTTP通信用ライブラリのDispatchを例に、 このライブラリをsbt consoleから利用する方法をまとめた。
まずは、build.sbtの依存ライブラリにDispatchを追加しておく。
// build.sbt name := "sbt-sample" version := "1.0" scalaVersion := "2.11.6" libraryDependencies += "net.databinder.dispatch" %% "dispatch-core" % "0.11.2" ``` build.sbtを用意したら、プロジェクトのディレクトリに移動して次のコマンドを実行。 ```bash: $ sbt console ``` すると、ライブラリの依存解決と、src以下のコンパイルが始まり、終わるとScalaREPL(対話式実行環境)が立ち上がる。 これは通常のScalaREPL(対話式シェル)と同じように見えるが、build.sbtに記述しているライブラリ及び、プロジェクト内のパッケージを利用できる。 まずは、Dispatchのパッケージをインポートしてみる。 ```bash: scala> import dispatch._, Defaults._ import dispatch._ import Defaults._ ``` このように、インポートが実行される。 すると次のように、REPLでDispatchを利用したプログラムが実行できる。 ```bash: scala> val svc = url("http://api.hostip.info/country.php") svc: dispatch.Req = Req(<function1>,Properties(NoBody)) scala> val country = Http(svc OK as.String) country: dispatch.Future[String] = >scala.concurrent.impl.Promise$DefaultPromise@33304f78 scala> country.foreach(println) XX ```
Scalaコマンドは、 Scalaパッケージにあるライブラリだけ使う場合に向いており、
sbt consoleはlibraryDependenciesが必要なライブラリを使いたい時や プロジェクトで定義しているクラスをREPLで使いたい時に向いています。
そのため冒頭にあったREPLでlibraryDependenciesが必要なライブラリを試したい時は、sbt consoleを使うといいです。
やってみたいこと
- 人数や年齢、アプリ流入後連続課金日数など、非負の整数しか取りえないデータに、型レベルの「非負制約」をはめる
- 人間や事物のペアやグループなど、要素の数が2以上の整数値を持たねばならないデータに対して、「2以上」もしくは「N以上」という数値制約を型制約として付ける(タプルやリストの長さ(length)を型制約として持たせる)
- 累積課金額データや連続課金日数と言ったデータに「N以上」という数値条件を「型制約」として持たせた上で、それらの型のデータを持つユーザを有料顧客として定義する。(通常のcase文によるパターンマッチによるデータ値の数値検査を、型レベルの検査に置き換える)
最後の項目は、Scalaの上限境界・下限境界のインスタンス生成制約の言語機能と組み合わせて、使ってみたい。想定する使い道は、次の2ステップです。
【 Step 1 】
まず「有料顧客」型のデータ型を__値制約(依存型)__で定義します。
【 Step 2 】
その次に、「有料顧客リスト」というコンテナオブジェクトに、「有料顧客」型のデータしか受け入れられないという__データ型制約__を定義する(上限境界・下限境界)。
Scalaの上限境界・下限境界制約については、すでに記事を書いてみました。
( 参考 )
また、自分で上限などを指定して範囲を指定できるPredicateも用意されています。
//2.5より小さい val `lessThan2.5`: Double Refined Less[W.`2.5`.T] = 1.8
//1から3まで
val inTheRange: Int Refined Interval.Closed[W.`1`.T, W.`3`.T] = 2
W.
1
.Tなどとしている部分では1というリテラルの型(Literal Singleton Type)を取り出しています。この型をLessやClosedのに渡してやることにより、コンパイル時に条件がチェックされるようになります。余談ですが、このLiteral Singleton TypeについてはSIP-23で改善案が提案されており、DottyではすでにW.
3
.Tなどとしなくても、val a: 3 = 3
のようにリテラルを直接使って型を表現することが可能になっているようです。
その他
以下も興味深い。
RacketやIdrisでは、さらに柔軟な依存型を定義できる