내가 개체 중 하나의 인스턴스 이름을 변경, 심지어 그때는 Int => Int => Int => Int
같은 기능이 작동하지 않습니다하지 않는 한 드미트로의 대답은 실제로 나를 위해 작동하지 않습니다 , 그리고 나는 Poly
값으로 작업하는 것이 정말 짜증이났다는 것을 알았습니다. 이전 답변을 디버깅하는 대신에, 저는 직접 작성하려고합니다.
import cats.Applicative
trait LiftCurried[F[_], I, O] {
type Out
def apply(f: F[I => O]): F[I] => Out
}
object LiftCurried extends LowPriorityLiftCurried {
implicit def liftCurried1[F[_]: Applicative, I, I2, O2](implicit
lc: LiftCurried[F, I2, O2]
): Aux[F, I, I2 => O2, F[I2] => lc.Out] = new LiftCurried[F, I, I2 => O2] {
type Out = F[I2] => lc.Out
def apply(f: F[I => I2 => O2]): F[I] => F[I2] => lc.Out =
(Applicative[F].ap(f) _).andThen(lc(_))
}
}
trait LowPriorityLiftCurried {
type Aux[F[_], I, O, Out0] = LiftCurried[F, I, O] { type Out = Out0 }
implicit def liftCurried0[F[_]: Applicative, I, O]: Aux[F, I, O, F[O]] =
new LiftCurried[F, I, O] {
type Out = F[O]
def apply(f: F[I => O]): F[I] => F[O] = Applicative[F].ap(f) _
}
}
조금 청소기 있는지 확인하는 아마 가능하지만, 나는 그것이 합리적인 읽을 그대로 찾을 :
하기는 꽤 잘 100 % 볼품없는 타입 클래스를 사용하여이 작업을 쓸 수 있습니다.
이 같은 콘크리트가 할 수 있습니다 :
def liftCurriedIntoOption[I, O](f: I => O)(implicit
lc: LiftCurried[Option, I, O]
): Option[I] => lc.Out = lc(Some(f))
을 그리고 우리는이 같은 일부 기능 작동하는지 보여줄 수 : 다음
val f: Int => Int => Int = x => y => x + y
val g: Int => Int => Int => Int = x => y => z => x + y * z
val h: Int => Int => Int => String => String = x => y => z => _ * (x + y * z)
그리고 :
scala> import cats.instances.option._
import cats.instances.option._
scala> val ff = liftCurriedIntoOption(f)
ff: Option[Int] => (Option[Int] => Option[Int]) = scala.Function1$$Lambda$1744/[email protected]
scala> val gg = liftCurriedIntoOption(g)
gg: Option[Int] => (Option[Int] => (Option[Int] => Option[Int])) = scala.Function1$$Lambda$1744/[email protected]
scala> val hh = liftCurriedIntoOption(h)
hh: Option[Int] => (Option[Int] => (Option[Int] => (Option[String] => Option[String]))) = scala.Function1$$Lambda$1744/[email protected]
지옥의 경우에도 몇 번 더 적용 할 수 있습니다.
scala> val hhhh = liftCurriedIntoOption(liftCurriedIntoOption(hh))
hhh: Option[Option[Option[Int]]] => (Option[Option[Option[Int]]] => (Option[Option[Option[Int]]] => (Option[Option[Option[String]]] => Option[Option[Option[String]]]))) = scala.Function1$$Lambda$1744/[email protected]
그래서 유형 괜찮아보고, 내가 생각하는 값 ...
scala> ff(Some(1))(Some(2))
res0: Option[Int] = Some(3)
scala> ff(Some(1))(None)
res1: Option[Int] = None
scala> hh(Some(1))(None)(None)(None)
res2: Option[String] = None
scala> hh(Some(1))(Some(2))(Some(3))(Some("a"))
res3: Option[String] = Some(aaaaaaa)
... 당신이 목표로 한 것입니다.
정말 멋졌습니다 ... 3 매개 변수 기능을 시도했을 때 분기 된대로 Lazy를 몇 가지 추가해야했습니다. –
그것으로 놀고 Poly 재귀에 의해 놀란 후, 나는 아직도 알아 내야 할 2 가지가 있다는 것을 깨달았다 ... Int에 묶지 않고 Option에 묶지 않는다. –