【发布时间】:2015-07-24 16:21:31
【问题描述】:
我已经开始对 Project Euler Problem #2 使用 Shapeless 解决方案。
我可以用这段代码将所有偶数小谎加在一起,直到 Nth 偶数:
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
}
}
现在我可以做:
val (evenFibs0, evenFibs1) = (Fibs(0), Fibs(1))
typed[_2](evenFibs0)
typed[_10](evenFibs1)
这就是我得到所有偶数的方法:我从序列 2、3、... 开始,然后每隔三个斐波那契数求和。
现在,我被困住了。我想拥有类似于takeWhile 的功能,所以我可以编写一个接受limit 的函数并返回我的偶数fib 的总和,其条款不超过该限制。有什么想法吗?
这是我迄今为止所做的努力:
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
}
}
这个想法是通过输出递归地减去限制,直到输出小于限制。我肯定能闻到有什么不对劲。我认为我根本不需要Diff。我也尝试了其他一些变化,但我一直卡住。编译时出现错误diverging implicit expansion for fibsN.
编辑:
我在想也许我可以构造我的Fibs 的HList,并使用带有谓词类型类的Selector 来模拟takeWhile。想法?
【问题讨论】:
标签: scala shapeless type-level-computation