我是新來的無形,一直在嘗試一些類型的水平編程。我把作爲我的第一個挑戰。項目歐拉斯卡拉無形代碼#1
我開始編寫正Scala代碼:
object ProjectEuler1 {
def e1(limit: Int) = (1 until limit).foldLeft(0) {
case (acc, x) if x % 3 * x % 5 == 0 => acc + x
case (acc, _) => acc
}
val out = e1(10)
assert(out == 23)
}
然後,我想出了利用poly
該工作不成形實現:
object ProjectEuler1Shapeless extends App {
import shapeless._
import nat._
import ops.nat._
import poly._
import test.typed
trait eLP extends Poly1 {
implicit def default[A <: Nat] = at[A] { _ => _0 }
}
object e extends eLP {
implicit def match3[A <: Nat](implicit ev: Mod.Aux[A, _3, _0]) = at[A](identity)
implicit def match5[A <: Nat](implicit ev: Mod.Aux[A, _5, _0]) = at[A](identity)
}
object sum extends Poly2 {
implicit def sum[A <: Nat, B <: Nat, Z <: Nat](implicit s: Sum.Aux[A, B, Z],
z: Witness.Aux[Z]) =
at[A, B] { (_, _) => z.value }
}
type _23 = Succ[_22]
val l = _1 :: _2 :: _3 :: _4 :: _5 :: _6 :: _7 :: _8 :: _9 :: HNil
val out = l.map(e).foldLeft(_0)(sum)
typed[_23](out)
}
接下來,我想改變的功能,使我不需要手動創建列表。相反,它接受一個「限制」作爲像普通斯卡拉代碼一樣的參數。我想出了這個:
object ProjectEuler1Shapeless2 extends App {
import shapeless._
import nat._
import ops.nat._
import test.typed
class E1[I <: Nat, N <: Nat]
trait ELP0 {
implicit def default[I <: Nat, M <: Nat] = new E1[I, _0]
}
trait ELP1 extends E1LP0 {
implicit def match3[A <: Nat](implicit ev: Mod.Aux[A, _3, _0]) = new E1[A, A]
implicit def match5[A <: Nat](implicit ev: Mod.Aux[A, _5, _0]) = new E1[A, A]
}
object E1 extends E1LP1 {
implicit def combine[I <: Nat, L <: Nat, M <: Nat](implicit e1: E1[I, L],
m: E1[Succ[I], M],
sum: Sum[L, M]) =
new E1[Succ[Succ[I]], sum.Out]
}
def e1[N <: Nat](limit: Nat)(implicit e: E1[limit.N, N], w: Witness.Aux[N]): N = w.value
val f1 = e1(1)
typed[_0](f1)
val f2 = e1(2)
typed[_0](f2)
val f3 = e1(3)
typed[_3](f3) // Does not compile!
}
我已經卡在這裏了。編譯器告訴我它發現_0
。我想這是從def default
拿起實例。
有關如何解決此問題的任何提示?我有一種感覺,我解決這個問題的策略也可能有點奇怪。任何關於如何使這個無形代碼更習慣的指針都非常感謝。
我最初的策略是創建一個hylomorphism。我注意到有一個unfold example in the shapeless git,但它的複雜性此刻逃脫了我。
這很美。正是我想要的,並且極具教育意義。一個偉大的教訓,如何使你的思維模式化。我一定會用這個答案作爲解決未來問題的參考。 – beefyhalo
不能'sumN'使用'P'和'Succ [P]'來代替'Succ [P]'和'Succ [Succ [P]]'還是有東西丟失? – beefyhalo
@beefyhalo啊,這是可能的 - 在今天的會議上寫這篇文章。 –