score:10
I find it a little easier to think about this problem inductively (at the type level, at least). First we can define a helper type class that returns N
if N
is a multiple of one of the numbers in M
, and _0
otherwise:
import shapeless._, nat._0, ops.nat.Mod
trait IfMultiple[N <: Nat, M <: HList] { type Out <: Nat }
trait LowPriorityIfMultiple {
type Aux[N <: Nat, M <: HList, Out0 <: Nat] = IfMultiple[N, M] {
type Out = Out0
}
implicit def isMultiple1[N <: Nat, H <: Nat, T <: HList](implicit
ifMultiple: IfMultiple[N, T]
): Aux[N, H :: T, ifMultiple.Out] = new IfMultiple[N, H :: T] {
type Out = ifMultiple.Out
}
}
object IfMultiple extends LowPriorityIfMultiple {
implicit def ifMultiple0[N <: Nat]: Aux[N, HNil, _0] =
new IfMultiple[N, HNil] {
type Out = _0
}
implicit def ifMultiple2[N <: Nat, H <: Nat, T <: HList](implicit
mod: Mod.Aux[N, H, _0]
): Aux[N, H :: T, N] = new IfMultiple[N, H :: T] {
type Out = N
}
}
And now we just need a type class to add up all these values from _0
to N - _1
:
import nat._1, ops.nat.Sum
trait SumOfMultiples[N <: Nat, M <: HList] extends DepFn0 { type Out <: Nat }
object SumOfMultiples {
type Aux[N <: Nat, M <: HList, Out0 <: Nat] = SumOfMultiples[N, M] {
type Out = Out0
}
def apply[N <: Nat, M <: HList](implicit
som: SumOfMultiples[N, M]
): Aux[N, M, som.Out] = som
implicit def sum0[M <: HList]: Aux[_1, M, _0] =
new SumOfMultiples[_1, M] {
type Out = _0
def apply(): _0 = _0
}
implicit def sumN[P <: Nat, M <: HList, NV <: Nat, PT <: Nat, NT <: Nat](implicit
ifMultiple: IfMultiple.Aux[P, M, NV],
som: Aux[P, M, PT],
sum: Sum.Aux[NV, PT, NT],
wit: Witness.Aux[NT]
): Aux[Succ[P], M, NT] = new SumOfMultiples[Succ[P], M] {
type Out = NT
def apply(): NT = wit.value
}
}
And then we're done:
import nat._, test.typed
val result = SumOfMultiples[_10, _3 :: _5 :: HNil]
typed[Succ[_22]](result())
Which compiles as expected.
It's worth noting that there are other ways you could solve this problem. You could create a type class that would provide Nat
ranges and then fold over that with a Poly2
using IfMultiple
. You could also define an IsMultiple
type class that just witnesses that N
is a multiple of one of the numbers in M
—my first quick attempt did this, but I ran into ambiguity issues, so I went with the similar version above. The implementation here is fairly straightforward, though, and unless you have other applications for e.g. Nat
ranges, I think it's a pretty reasonable solution.
Source: stackoverflow.com
Related Query
- Scala Shapeless Code for Project Euler #1
- Scala Shapeless Code for Project Euler #2
- Code coverage for scala with separate test project in java
- How to get SonarQube code coverage for scala project
- Sonarqube, getting Zero Code Coverage for scala project
- Enforcing Java version for Scala project in sbt?
- Code Coverage Tools for Scala
- How do I find the correct Maven archetype project for developing with Scala in Eclipse?
- What is the accepted/recommended syntax for Scala code with lots of method-chaining?
- Errors in Eclipse for Scala project generated by Play Framework
- How do you impose scala code coverage specifically for integration tests?
- Attaching sources in IntelliJ IDEA for scala project
- Gradle init project for Scala application
- Is there a tool for Scala to clean all the unused imports from all the code files?
- How do you open a single project for Java, Scala and JRuby in Eclipse?
- Functional style for this Scala code
- Using Scala with Gradle for Android project
- How to synchronize Intellij and sbt builds for a scala project
- scala code causes error in eclipse for playframework-2.0
- Partial EMMA code coverage in Scala Case Class for IntelliJ IDEA 10.5
- How to configure code style for Scala in IntelliJ IDEA
- How do scala developers cope with incorrect IDE(Idea) errors in scala code with shapeless
- Can I compile a Scala project with mixed java and scala code with dependencies both ways in Maven?
- How to custom code folding for Scala in intelliJ IDEA?
- how can I interop kotlin code in an existing SBT scala project
- Including Hyperic Sigar library within jar while using sbt assembly for Scala project
- Scala / Java Sandbox for untrusted code
- Emacs project management for Scala
- how to debug scala sbt project in vs code
- How to organize code for multiple scala versions and differents dependencies
More Query from same tag
- Loop Scala both ways depending on parameters
- Play 2.1 sbt-jasmine-plugin getting not found: value jasmineSettings error
- How to handle options with a default
- Convert Traversable[T] to Stream[T] without traversing or stack overflow
- Spark - change parallelism during execution
- Weird scala snippet in sjson (macro?)
- How to send actor a tell message when a URL is accessed?
- List of Option to list of String in scala
- Do we need Lzocodec for groupBy function in Scala Spark?
- Spark Scala: DateDiff of two columns by hour or minute
- Serialize/De-serialize Scala future
- Macros: knownDirectSubclasses broken with nested type?
- Unsupported literal type class scala.runtime.BoxedUnit
- Solving dynamic programming problems using functional programming
- Retrieve cookie value with Gatling
- The main function in OCaml
- Style sheets and body and head tags in programmatically produced HTML
- What date/time class should I be mapping too?
- Using underscore in scala map function
- How to restrict access to local actor
- Declare a generic class in scala without square brackets
- Akka http testkit, how to test streaming response timing
- Entities do not auto relocate to joined nodes
- Spark Accumulators: Is the right accumulator sometimes many or always one?
- Gatling SBT execute a specific simulation
- Scala: Transform and replace values of Spark DataFrame with nested json structure
- Evaluate String as a generic function or function call in Scala
- Giving up DI and use BDD and Integration Tests
- How to map a map of tuples into a tuple of maps in Scala?
- Slick 1.0.0 | Return Expression From For Comprehension