scala - Compile-time Check on Sum of Nat's? -
i attempted write typeclass, sumeq5
, such hlist
type parameter's first 2 fields add 5
:
trait sumeq5[a] object sumeq5 { def apply[l <: hlist](implicit ev: sumeq5[l]): sumeq5[l] = ev implicit def sumeq5ev[l <: hlist, <: nat, b <: nat]( implicit hcons: ishcons.aux[l, a, b :: hnil], ev: sum.aux[a, b, _5] ): sumeq5[l] = new sumeq5[l] {} }
but doesn't appear work:
import shapeless._ import shapeless.nat._ import net.sumeq5 scala> sumeq5[_0 :: _5 :: hnil] <console>:19: error: not find implicit value parameter ev: net.sumeq5[shapeless.::[shapeless.nat._0,shapeless.:: [shapeless.nat._5,shapeless.hnil]]] sumeq5[_0 :: _5 :: hnil]
please give me hint why _0 :: _5 :: hnil
not have evidence 2 nat
's equal 5.
edit
updated question per denis rosca's in shapeless's gitter.
dale wijnand , marcus henry pointing in right direction if want generalize hlist
s of arbitrary length, if want accommodate 2 element hlist
s, following rather simpler solution,
scala> import shapeless._, nat._, ops.nat._ import shapeless._ import nat._ import ops.nat._ scala> :paste // entering paste mode (ctrl-d finish) trait sumeq5[a] object sumeq5 { def apply[l <: hlist](implicit ev: sumeq5[l]): sumeq5[l] = ev implicit def sumeq5ab[a <: nat, b <: nat] (implicit ev: sum.aux[a, b, _5]): sumeq5[a :: b :: hnil] = new sumeq5[a :: b :: hnil] {} } // exiting paste mode, interpreting. defined trait sumeq5 defined object sumeq5 scala> sumeq5[_0 :: _5 :: hnil] res0: sumeq5[_0 :: _5 :: hnil]] = sumeq5$$anon$1@658c5e59
the main difference here instance explicitly defined 2 element lists rather being defined lists in general proviso there exists proof list has 2 elements.
following dale's update, can generalize accommodate hlist
s @ least 2 (rather two) elements, again without additional witnesses,
scala> import shapeless._, nat._, ops.nat._ import shapeless._ import nat._ import ops.nat._ scala> :paste // entering paste mode (ctrl-d finish) trait sumeq5[a] object sumeq5 { def apply[l <: hlist](implicit ev: sumeq5[l]): sumeq5[l] = ev implicit def sumeq5ab[a <: nat, b <: nat, t <: hlist] (implicit ev: sum.aux[a, b, _5]): sumeq5[a :: b :: t] = new sumeq5[a :: b :: t] {} } // exiting paste mode, interpreting. defined trait sumeq5 defined object sumeq5 scala> sumeq5[_0 :: _5 :: hnil] res0: sumeq5[_0 :: _5 :: hnil]] = sumeq5$$anon$1@658c5e59
Comments
Post a Comment