0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Scala】型シグネチャにユーザ定義の依存型refinedの値制約を付けると、val初期化宣言時に変数代入(名前束縛)できない

Last updated at Posted at 2021-11-09

( 後記 )

以下のコードで実行できることがわかりました。

【 わかったこと 】

  • Refinedは、コンパイル時にオブジェクトの値制約が充足されているかどうかをチェックする。
  • リテラル値(5, "abc", 'a'など)はコンパイルが行われる時点で、値が分かるので、依存型Refinedの値制約を帯びたオブジェクトの初期化宣言として受け入れられる。
  • 変数x, yなどに格納(名前束縛)された値の中身は、コンパイル時に内容を(コンパイラが)判断できない。そのため、依存型Refinedの値制約を帯びたオブジェクトの初期化宣言として受け入れらない(エラーが変える)。
  • RefineV()関数を変数x, yにかけると、上記が解決される。
  • RefineV()関数を、Int型のオブジェクトに適用すると、Either型オブジェクトが出力される。
  • Eitherオブジェクトから、Either.right.get関数で値を取り出す
  • 取り出した値(Int型オブジェクトのリテラル値)を初期化変数として、依存型Refinedの値制約を帯びたオブジェクトを宣言する(val宣言またはvar宣言)

成功するコード

sbtConsole
scala> val positive: Int Refined Positive = refineV[Positive](x).right.get
warning: 2 deprecations (since 2.13.0); for details, enable `:setting -deprecation` or `:replay -deprecation`
val positive: eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Positive] = 3

scala> positive
val res35: eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Positive] = 3

scala> 
sbtConsole
scala> val temp = refineV[Positive](x).right.get
warning: 2 deprecations (since 2.13.0); for details, enable `:setting -deprecation` or `:replay -deprecation`
val temp: eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Positive] = 3

scala> temp
val res34: eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Positive] = 3

scala> val positive: Int Refined Positive = temp
val positive: eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Positive] = 3

scala> positive
val res35: eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Positive] = 3

scala> 

Int型のオブジェクトを格納(名前束縛)した変数だけでなく、String型を格納した変数や、List型を格納した変数を扱う場合も含めて、以下の記事で解説しています。

この記事はここから始まります

以下の方も同じ問題に直面している。

package xxx 

import eu.timepit.refined._ 
import eu.timepit.refined.api.{Refined, Validate} 
import eu.timepit.refined.auto._ 
import eu.timepit.refined.numeric._ 
import eu.timepit.refined.api.Refined 
import eu.timepit.refined.numeric.Interval 

object Lala { 
   type X = Integer Refined Positive 
   def lala(x: Int): Unit = { 
   val lala: X = refineV[X](x) 
   } 
} 

、私は、このエラーメッセージが表示されます:ポジ型のための検証の実装が欠落しているようだ

Error:(13, 29) could not find implicit value for parameter v: >eu.timepit.refined.api.Validate[Int,xxx.Lala.X] val lala: X = refineVX

Error:(13, 29) not enough arguments for method apply: (implicit v: >eu.timepit.refined.api.Validate[Int,xxx.Lala.X])Either[String,eu.timepit.refined.api.R>efined[Int,xxx.Lala.X]] in class RefinePartiallyApplied. Unspecified value parameter >v. val lala: X = refineVX

いるから。 PositiveタイプのValidate特性のインスタンスを見つけるのに役立つ人がいるかどうか疑問に思っていました>か?あるいは、私はそのようなインスタンスを自分で提供すべきですか?

  • refinedのバージョン 0.9.27を読み込んでいます。
build.sbt
scalaVersion := "2.13.6"
libraryDependencies += "eu.timepit" %% "refined" % "0.9.27"
  • sbt consoleでREPLを起動。
Terminal
% 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/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/refined_trial/)
[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> 
sbtConsole
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> 

refinedで型の値制約を定義

sbtConsole
scala> type ConditionedInt = Int Refined Interval.ClosedOpen[10000, 10000000]
type ConditionedInt

scala> 

リテラル値による値束縛(代入)を伴うオブジェクト宣言はできる

sbtConsole
scala> val a: ConditionedInt = 100000
val a: ConditionedInt = 100000

scala> a
val res13: ConditionedInt = 100000

scala> val b: ConditionedInt = 100
                               ^
       error: Left predicate of (!(100 < 10000) && (100 < 10000000)) failed: Predicate (100 < 10000) did not fail.

scala> 

別の変数の名前束縛(代入)伴うオブジェクト宣言はできなくなる

sbtConsole
scala> val john_tuple = ("John", 100000)
val john_tuple: (String, Int) = (John,100000)

cala> val (name, sales_volume) = john_tuple
val name: String = John
val sales_volume: Int = 100000

scala> name
val res11: String = John

scala> sales_volume
val res12: Int = 100000

scala>
  • 以下がエラーになる
  • リテラル値しかダメと言われる
errorメッセージ
compile-time refinement only works with literals
sbtConsole
scala> val a: ConditionedInt = sales_volume
                               ^
       error: compile-time refinement only works with literals

scala>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?