Zacząłem od mojego Shapeless rozwiązania do Project Euler Problem #2.Scala Shapeless Code for Project Euler # 2
mogę podsumować wspólnie wszystkie parzyste FIBS do Nth
choćby jednego z tym kodem:
import shapeless._, nat._, ops.nat.Sum
trait Fibonacci[N <: Nat] { type Out <: Nat }
object Fibonacci {
type Aux[N <: Nat, Out0 <: Nat] = Fibonacci[N] { type Out = Out0 }
def apply[N <: Nat](i: Nat)(implicit fib: Aux[i.N, N], n: Witness.Aux[N]):N = n.value
implicit val fib0 = new Fibonacci[_0] { type Out = _2 }
implicit val fib1 = new Fibonacci[_1] { type Out = _3 }
implicit def fibN[I <: Nat, L <: Nat, M <: Nat](implicit l: Aux[I, L],
m: Aux[Succ[I], M],
sum: Sum[L, M]) =
new Fibonacci[Succ[Succ[I]]] { type Out = sum.Out }
}
trait Fibs[N <: Nat] { type Out <: Nat }
object Fibs {
type Aux[N <: Nat, Out0 <: Nat] = Fibs[N] { type Out = Out0 }
def apply[N <: Nat](i: Nat)(implicit fibs: Aux[i.N, N], n: Witness.Aux[N]):N = n.value
implicit def fibs0(implicit f: Fibonacci[_0]) = new Fibs[_0] { type Out = f.Out }
implicit def fibsN[N <: Nat, R <: Nat, Z <: Nat](implicit fib: Fibonacci.Aux[Succ[Succ[Succ[N]]], R],
fibs: Aux[N, Z],
sum: Sum[R, Z]) =
new Fibs[Succ[N]] {
type Out = sum.Out
}
}
Teraz mogę zrobić:
val (evenFibs0, evenFibs1) = (Fibs(0), Fibs(1))
typed[_2](evenFibs0)
typed[_10](evenFibs1)
ten sposób uzyskać wszystkie nawet FIBS: Zaczynam od sekwencji 2, 3, ... i podsumowuję co trzecią liczbę Fibonacciego.
Teraz utknąłem. Chciałbym mieć funkcjonalność podobną do takeWhile
, więc mogę napisać funkcję, która akceptuje limit
i zwraca sumę moich nawet kłamstw, których warunki nie przekraczają tego limitu. Jakieś pomysły?
Oto mój wysiłek na co starałem dotąd:
trait EvenFibsWithLimit[N <: Nat, M <: Nat] { type Out <: Nat }
trait LowPriorityFibs3 {
type Aux[N <: Nat, M <: Nat, Out0 <: Nat] = EvenFibsWithLimit[N, M] { type Out = Out0 }
implicit def fibs0[M <: Nat] = new EvenFibsWithLimit[_0, M] { type Out = _0 }
implicit def fibsGT[N <: Nat, M <: Nat, O <: Nat](implicit f: EvenFibsWithLimit[N, M],
fib: Fibs.Aux[N, O],
l: ops.nat.LT[M, O]) = f
}
object EvenFibsWithLimit extends LowPriorityFibs3 {
def apply[N <: Nat, O <: Nat](limit: Nat)(implicit fibs: Aux[N, limit.N, O],
o: Witness.Aux[O]): O = o.value
implicit def fibsN[N <: Nat, M <: Nat, O <: Nat](implicit f: EvenFibsWithLimit[N, M],
f2: Fibs.Aux[Succ[N], O],
d: ops.nat.Diff[M, O]) =
new EvenFibsWithLimit[Succ[N], d.Out] {
type Out = O
}
}
Ideą było rekursywnie odjąć limitu przez wyjście aż wyjściowa jest mniejsza niż limit. Mogę zdecydowanie poczuć, że coś jest nie tak. Nie sądzę, żebym potrzebował Diff
w ogóle. Próbowałem też innych odmian, ale wciąż utknąłem. Kiedy mogę skompilować, pojawia się błąd diverging implicit expansion for fibsN.
EDIT:
Myślałam może uda mi się skonstruować HList
z moich Fibs
i korzystania Selector
z typeclass kwantyfikatorów symulować takeWhile
. Myśli?
Fajna technika. Zaczynam rozumieć teraz, dzięki. – beefyhalo