Используется уточнено для повторной попытки?
Используя уточненный, я попытался определить f
:
import eu.timepit.refined._
import eu.timepit.refined.api.Refined
import eu.timepit.refined.auto._
import eu.timepit.refined.numeric._
// if action 'succeeds', return 'good'; otherwise re-try, subtracting count by 1
scala> def f[A](action: => A, success: A => Boolean, count: Int Refined Positive): String =
| if( success(action) ) "good" else f(action, success, count - 1)
<console>:32: error: compile-time refinement only works with literals
if( success(action) ) "good" else f(action, success, count - 1)
^
Так как это не сработало, я прибег к:
def fEither[A](action: => A, success: A => Boolean, count: Either[String, Int Refined Positive]): String = {
println(count)
if( success(action) ) "good"
else {
count match {
case Right(c) => fEither(action, success, refineV[Positive](c - 1))
case Left(_) => "bad"
}
}
}
scala> fEither[Int](42, _ => false, Right( refineMV[Positive]( 2 ) ) )
Right(2)
Right(1)
Left(Predicate failed: (0 > 0).)
res2: String = bad
В идеале я хотел бы преобразовать эту программу Idris в Scala:
f : (action : a) -> (success: a -> Bool) -> (n : Nat) -> String
f action success (S n) = if (success action) then "good" else f action success n
f _ _ Z = "bad"
*scratch> f 42 (const False) 2
"bad" : String
*scratch> f 42 (const False) 0
"bad" : String
но я не уверен в совпадении Nat
возможность.
1 ответ
- Уточнение, которое вы хотите использовать,
NonNegative
, так0
является допустимым значением. - Код Идриса существенно различает
n - 1
все еще натуральное число или нет, так что вы можете сделать это напрямую, используя версию во время выполненияrefineV
:
def f[A](action: => A, success: A => Boolean, count: Int Refined NonNegative): String =
refineV[NonNegative](count - 1) match {
case Right(n) => if (success(action)) "good" else f(action, success, n)
case Left(_) => "bad"
}
PS Возможно, вам понадобится несколько списков параметров, так как Scala, скорее всего, не сможет определить тип A
правильно на сайте вызова