Ho iniziato la mia soluzione di Shapeless a Project Euler Problem #2.Codice senza forma Scala per Project Euler # 2
Posso riassumere insieme tutti i anche frottole fino al Nth
anche uno con questo codice:
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
}
}
Ora posso fare:
val (evenFibs0, evenFibs1) = (Fibs(0), Fibs(1))
typed[_2](evenFibs0)
typed[_10](evenFibs1)
Questo è come ottenere tutti anche frottole: Comincio con la sequenza 2, 3, ..., e riassumo ogni terzo numero di Fibonacci.
Ora, sono bloccato. Mi piacerebbe avere funzionalità simili a takeWhile
, quindi posso scrivere una funzione che accetta uno limit
e restituisce la somma delle mie fib addirittura pari i cui termini non superano tale limite. Qualche idea?
Ecco il mio sforzo per quello che ho provato finora:
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
}
}
L'idea era quella di sottrarre in modo ricorsivo il limite per l'uscita fino a quando l'uscita è inferiore al limite. Posso sicuramente sentire l'odore di qualcosa. Non penso di aver bisogno del Diff
.. Ho provato anche altre varianti, ma continuo a rimanere bloccato. Quando compilo, ottengo l'errore diverging implicit expansion for fibsN.
EDIT:
Stavo pensando forse posso costruire un HList
della mia Fibs
, e utilizzare Selector
con un typeclass predicato per simulare un takeWhile
. Pensieri?
Bella tecnica. Sto iniziando a capire le cose ora, grazie. – beefyhalo