1
0

More than 1 year has passed since last update.

【Scala】関数の引数にRefined値制約を付ける場合、その引数にリテラル値ではない「変数x」が渡された場合も正常に動作させる方法

Posted at

Refinedで定義された値制約が付いたオブジェクトは、数値リテラル(1, 175など)や文字列リテラル("abc"など)を与えると、オブジェクトを初期化宣言させることができます。

他方で、すでに定義済みの変数(x, y, customer_name, sales_volumeなど)で初期化宣言をしようとすると、「リテラル値でないと受付けられません」というエラーメッセージが吐かれてしまいます。

そのため、関数の引数にRefined値制約を付ける場合、その引数にリテラル値ではない「変数x」が渡された場合は、エラーが発生してしまうことになります。

そうした事例が、以下のウェブページで報告されています。

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

この関数は、以下のように定義すると、引数として、リテラル値の整数が渡された場合も、変数に格納(名前束縛)された整数が渡された場合も、値検査を行った上で、正常に動作します。

sbtConsole
scala> type X = Integer Refined Positive
type X

scala> 
scala> def lala(x: Int):Unit = {
     |    val lala: X = refineV[Positive](x).right.get
     |    println(x)
     | }
warning: 2 deprecations (since 2.13.0); for details, enable `:setting -deprecation` or `:replay -deprecation`
def lala(x: Int): Unit

scala>
sbtConsole
scala> lala(3)
3

scala> val sample_number = 7
val sample_number: Int = 7

scala> lala(sample_number)
7

scala>
  • 値制約条件Xを充足しない整数(0と負整数)が渡された場合は、ちゃんとエラーになります。
  • ここは、errorを発生させずに、Either型かOption側で対応させたいところではあります。
sbtConsole
scala> lala(-10)
java.util.NoSuchElementException: Either.right.get on Left
  at scala.util.Either$RightProjection.get(Either.scala:696)
  at lala(<console>:2)
  ... 35 elided

scala> val negative_number = -7
val negative_number: Int = -7

scala> lala(negative_number)
java.util.NoSuchElementException: Either.right.get on Left
  at scala.util.Either$RightProjection.get(Either.scala:696)
  at lala(<console>:2)
  ... 35 elided

scala> val zero_number = 0
val zero_number: Int = 0

scala> lala(zero_number)
java.util.NoSuchElementException: Either.right.get on Left
  at scala.util.Either$RightProjection.get(Either.scala:696)
  at lala(<console>:2)
  ... 35 elided

scala> 

上記のコードの書き方について、背景は以下の記事で解説しています。

1
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
1
0