Skip to content

Commit d30a6ac

Browse files
authored
rebase to latest work on master. (#269)
1 parent b87558e commit d30a6ac

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

build.sbt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ lazy val scala_akka = (project in file("scala-akka"))
117117

118118
val monocleVersion = "2.0.4"
119119
val slickVersion = "3.3.2"
120+
val shapelessVersion = "2.3.3"
120121
val scalazVersion = "7.3.2"
121122
lazy val scala_libraries = (project in file("scala-libraries"))
122123
.settings(
@@ -128,6 +129,8 @@ lazy val scala_libraries = (project in file("scala-libraries"))
128129
"com.github.julien-truffaut" %% "monocle-law" % monocleVersion % "test",
129130
"com.typesafe.slick" %% "slick" % slickVersion,
130131
"com.h2database" % "h2" % "1.4.200",
132+
"com.chuusai" %% "shapeless" % shapelessVersion,
133+
"com.h2database" % "h2" % "1.4.200",
131134
"org.scalaz" %% "scalaz-core" % scalazVersion,
132135
"junit" % "junit" % "4.13" % Test
133136
)
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package com.baeldung.scala.shapeless
2+
3+
import org.scalatest.matchers.should.Matchers
4+
import org.scalatest.wordspec.AnyWordSpec
5+
import shapeless.ops.record.Keys
6+
import shapeless.{Generic, HNil, Inl, Inr, _}
7+
8+
class ShapelessSpecs extends AnyWordSpec with Matchers {
9+
val hlist: Int :: Double :: String :: Boolean :: HNil =
10+
1 :: 1.0 :: "One" :: false :: HNil
11+
12+
case class User(name: String, age: Int)
13+
14+
"HList" should {
15+
"return the first element of hlist" in {
16+
assert(hlist.head == 1)
17+
}
18+
19+
"return the two frist elements of hlist" in {
20+
assert(hlist.take(2) == 1 :: 1.0 :: HNil)
21+
}
22+
23+
"return the tail of hlist" in {
24+
assert(hlist.tail == 1.0 :: "One" :: false :: HNil)
25+
}
26+
}
27+
28+
"Coproduct" should {
29+
sealed trait TrafficLight
30+
case class Green() extends TrafficLight
31+
case class Red() extends TrafficLight
32+
case class Yellow() extends TrafficLight
33+
34+
"convert sealed trait coproduct to shapeless coproduct" in {
35+
val gen = Generic[TrafficLight]
36+
val green = gen.to(Green())
37+
val red = gen.to(Red())
38+
val yellow = gen.to(Yellow())
39+
assert(green == Inl(Green()))
40+
assert(red == Inr(Inl(Red())))
41+
assert(yellow == Inr(Inr(Inl(Yellow()))))
42+
}
43+
44+
"convert back shapeless coproduct to sealed trait product type" in {
45+
val gen = Generic[TrafficLight]
46+
val green = gen.from(Inl(Green()))
47+
val red = gen.from(Inr(Inl(Red())))
48+
val yellow = gen.from(Inr(Inr(Inl(Yellow()))))
49+
assert(green == Green())
50+
assert(red == Red())
51+
assert(yellow == Yellow())
52+
}
53+
54+
"create coproduct" in {
55+
import shapeless._
56+
object Green
57+
object Red
58+
object Yellow
59+
type Light = Green.type :+: Red.type :+: Yellow.type :+: CNil
60+
val light = Coproduct[Light](Green)
61+
light.filter
62+
assert(light.select[Green.type] == Some(Green))
63+
assert(light.select[Yellow.type] == None)
64+
}
65+
66+
}
67+
68+
"Generic" should {
69+
"Convert case class to corresponding HList product type" in {
70+
val user = User("John", 25)
71+
val userHList = Generic[User].to(user)
72+
assert(userHList == "John" :: 25 :: HNil)
73+
}
74+
75+
"Convert back hlist to corresponding case class product type" in {
76+
val user = User("John", 25)
77+
val userHList = Generic[User].to(user)
78+
val userRecord = Generic[User].from(userHList)
79+
assert(user == userRecord)
80+
}
81+
82+
"Convert tuple to HList product type" in {
83+
val user = ("John", 25)
84+
val userHList = Generic[(String, Int)].to(user)
85+
assert(userHList == "John" :: 25 :: HNil)
86+
}
87+
88+
"Operations on tuple" should {
89+
import shapeless.syntax.std.tuple._
90+
val tuple = ("John", 25, true)
91+
92+
"take head from tuple" in {
93+
val head = tuple.head
94+
assert(head == "John")
95+
}
96+
97+
"drop two element from tuple" in {
98+
val res = tuple.drop(2)
99+
assert(res == Tuple1(true))
100+
}
101+
102+
"concat two tuple to one" in {
103+
val list = tuple ++ (1.3, "foo")
104+
assert(list == ("John", 25, true, 1.3, "foo"))
105+
}
106+
}
107+
108+
"Convert back hlist to corresponding tuple product type" in {
109+
val user = ("John", 25)
110+
val userHList = Generic[(String, Int)].to(user)
111+
val userRecord = Generic[(String, Int)].from(userHList)
112+
assert(user == userRecord)
113+
}
114+
}
115+
116+
"LabelledGeneric" should {
117+
import shapeless._
118+
import record._
119+
val user = User("John", 25)
120+
val userGen = LabelledGeneric[User]
121+
val userLaballedRecord = userGen.to(user)
122+
123+
"read name field from labelled Hlist" in {
124+
assert(userLaballedRecord('name) == "John")
125+
}
126+
127+
"return list of keys from labelled Hlist" in {
128+
val keys = Keys[userGen.Repr]
129+
assert(keys() == 'name :: 'age :: HNil)
130+
}
131+
132+
"return list of values from labelled Hlist" in {
133+
assert(userLaballedRecord.values == "John" :: 25 :: HNil)
134+
}
135+
}
136+
137+
"Polymorphic function" should {
138+
"calculate length of variant input types" in {
139+
import shapeless._
140+
object polyLength extends Poly1 {
141+
implicit val listCase = at[List[Int]](i => i.length)
142+
implicit val stringCase = at[String](d => d.length)
143+
implicit val arrayCase = at[Array[Int]](d => d.length)
144+
}
145+
146+
val list = List(1, 2) :: "123" :: Array(1, 2, 3, 4) :: HNil
147+
148+
assert(polyLength(List(1, 2)) == 2)
149+
assert(polyLength("123") == 3)
150+
assert(polyLength(Array(1, 2, 3, 4)) == 4)
151+
assert(list.map(polyLength) == 2 :: 3 :: 4 :: HNil)
152+
}
153+
}
154+
}

0 commit comments

Comments
 (0)