Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 82081c1

Browse files
committed
Merge pull request milessabin#532 from tpolecat/ToSizedHList
Add ToSizedHList
2 parents 888d78d + 69bf919 commit 82081c1

File tree

5 files changed

+74
-1
lines changed

5 files changed

+74
-1
lines changed

core/src/main/scala/shapeless/ops/sizeds.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ object sized {
99
*
1010
* @author Alexandre Archambault
1111
*/
12-
trait ToHList[-Repr, L <: Nat] {
12+
trait ToHList[-Repr, L <: Nat] extends Serializable {
1313
type Out <: HList
1414
def apply(s: Sized[Repr, L]): Out
1515
}

core/src/main/scala/shapeless/ops/traversables.scala

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,50 @@ object traversable {
5151
else for(h <- l.head.cast[OutH]; t <- flt(l.tail)) yield h :: t
5252
}
5353
}
54+
55+
/**
56+
* Type class supporting type safe conversion of `Traversables` to `HLists` of a specific length.
57+
*
58+
* @author Rob Norris
59+
*/
60+
trait ToSizedHList[CC[T] <: GenTraversable[T], A, N <: Nat] extends Serializable {
61+
type Out
62+
def apply(cc: CC[A]): Out
63+
}
64+
65+
/**
66+
* `ToSizedHList` type class instances.
67+
*
68+
* @author Rob Norris
69+
*/
70+
object ToSizedHList {
71+
72+
def apply[CC[T] <: GenTraversable[T], A, N <: Nat](
73+
implicit ev: ToSizedHList[CC, A, N]
74+
): ToSizedHList.Aux[CC, A, N, ev.Out] =
75+
ev
76+
77+
import syntax.sized._
78+
import ops.nat._
79+
import ops.sized._
80+
81+
type Aux[CC[T] <: GenTraversable[T], A, N <: Nat, Out0] =
82+
ToSizedHList[CC, A, N] {
83+
type Out = Out0
84+
}
85+
86+
implicit def instance[CC[T] <: GenTraversable[T], A, N <: Nat](
87+
implicit gt: CC[A] => GenTraversableLike[A, CC[A]],
88+
ac: AdditiveCollection[CC[A]],
89+
ti: ToInt[N],
90+
th: ToHList[CC[A], N]
91+
): Aux[CC, A, N, Option[th.Out]] =
92+
new ToSizedHList[CC, A, N] {
93+
type Out = Option[th.Out]
94+
def apply(as: CC[A]): Out =
95+
as.sized[N].map(_.toHList)
96+
}
97+
98+
}
99+
54100
}

core/src/main/scala/shapeless/syntax/std/traversables.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,21 @@ import scala.collection.GenTraversable
2727
* typed [[shapeless.HList]] if possible.
2828
*
2929
* @author Miles Sabin
30+
* @author Rob Norris
3031
*/
3132
object traversable {
3233
implicit def traversableOps[T <% GenTraversable[_]](t : T) = new TraversableOps(t)
34+
implicit def traversableOps2[CC[T] <: GenTraversable[T], A](as: CC[A]) = new TraversableOps2(as)
3335
}
3436

3537
final class TraversableOps[T <% GenTraversable[_]](t : T) {
3638
import ops.traversable._
3739

3840
def toHList[L <: HList](implicit fl : FromTraversable[L]) : Option[L] = fl(t)
3941
}
42+
43+
final class TraversableOps2[CC[T] <: GenTraversable[T], A](as: CC[A]) {
44+
import ops.traversable._
45+
46+
def toSizedHList(n: Nat)(implicit ts: ToSizedHList[CC, A, n.N]): ts.Out = ts(as)
47+
}

core/src/test/scala/shapeless/hlist.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class HListTests {
3434
type SI = Set[Int] :: HNil
3535
type OI = Option[Int] :: HNil
3636

37+
type III = Int :: Int :: Int :: HNil
38+
3739
type SISS = Set[Int] :: Set[String] :: HNil
3840
type OIOS = Option[Int] :: Option[String] :: HNil
3941

@@ -3136,4 +3138,12 @@ class HListTests {
31363138
illTyped(""" (1 :: "a" :: 3 :: HNil).slice(0, 4) """)
31373139
illTyped(""" (1 :: "a" :: 3 :: HNil).slice(1, 0) """)
31383140
}
3141+
3142+
@Test
3143+
def testToSizedHList {
3144+
val ns = List(1,2,3,4)
3145+
assertTypedEquals[Option[III]](None, ns.toSizedHList(3))
3146+
assertTypedEquals[Option[IIII]](Some(1 :: 2 :: 3 :: 4 :: HNil), ns.toSizedHList(4))
3147+
}
3148+
31393149
}

core/src/test/scala/shapeless/serialization.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,15 @@ class SerializationTests {
900900
def testTraversable {
901901
type L = Int :: String :: Boolean :: HNil
902902
assertSerializable(FromTraversable[L])
903+
904+
// To satisfy serialization of `ToSizedHList` we must provide a serializable `IsTraversableLike`
905+
// that will get picked up for the `ops.sized.ToHList` we're using. I'm not convinced that this
906+
// is entirely ethical since real-life usage will almost certainly fail, or at least until the
907+
// instance in stdlib is fixed. - rob/tpolecat
908+
import scala.collection.generic.IsTraversableLike
909+
implicit val hack: IsTraversableLike[List[Int]] { type A = Int } = null
910+
assertSerializable(ToSizedHList[List, Int, _4])
911+
903912
}
904913

905914
@Test

0 commit comments

Comments
 (0)