Ich habe mit meiner Shapeless-Lösung zu Project Euler Problem #2 begonnen.Scala Formloser Code für Projekt Euler # 2
kann ich Summe zusammen, alle noch fibs bis zum Nth
auch ein mit diesem Code:
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
}
}
Jetzt kann ich tun:
val (evenFibs0, evenFibs1) = (Fibs(0), Fibs(1))
typed[_2](evenFibs0)
typed[_10](evenFibs1)
Dies ist, wie ich alles selbst fibs erhalten: Ich beginne mit der Sequenz 2, 3, ... und fasse jede dritte Fibonacci-Zahl zusammen.
Jetzt bin ich fest. Ich hätte gerne eine ähnliche Funktionalität wie takeWhile
, also kann ich eine Funktion schreiben, die eine limit
akzeptiert und die Summe meiner geraden Flops zurückgibt, deren Bedingungen diese Grenze nicht überschreiten. Irgendwelche Ideen?
Hier ist meine Mühe für das, was ich bisher ausprobiert habe:
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
}
}
Die Idee, die Grenze durch die Ausgabe rekursiv zu subtrahieren war, bis der Ausgang kleiner als der Grenzwert ist. Ich kann definitiv riechen, dass etwas aus ist. Ich glaube nicht, dass ich überhaupt Diff
brauche. Ich habe auch einige andere Varianten ausprobiert, aber ich bleibe stecken. Wenn ich kompilieren, erhalte ich die Fehler diverging implicit expansion for fibsN.
EDIT:
Ich dachte, vielleicht kann ich ein HList
meiner Fibs
, konstruieren und Selector
mit einem Prädikat typeclass verwenden, um eine takeWhile
zu simulieren. Gedanken?
Schöne Technik. Ich fange jetzt an, den Dreh raus zu bekommen, danke. – beefyhalo