Reputation: 864
Having
(Some(1), 2, Some(3))
I expect to get
(Some(1), Some(2), Some(3))
With shapeless is it possible to do so?
Upvotes: 6
Views: 751
Reputation: 23056
Yes it is,
scala> import shapeless._, syntax.std.tuple._
import shapeless._
import syntax.std.tuple._
scala> :paste
// Entering paste mode (ctrl-D to finish)
object opt extends opt0 {
implicit def optId[T <: Option[_]] = at[T](identity)
}
trait opt0 extends Poly1 {
implicit def default[T] = at[T](Option(_))
}
// Exiting paste mode, now interpreting.
defined object opt
defined trait opt0
scala> (Some(1), 2, Some(3)) map opt
res0: (Some[Int], Option[Int], Some[Int]) = (Some(1),Some(2),Some(3))
You'll notice that the Some[Int]
's at the first and last position have been preserved whereas the lifted middle element is typed as Option[Int]
. I've worked on the assumption that what you actually intended was something like this,
scala> (Option(1), 2, Option(3)) map opt
res1: (Option[Int], Option[Int], Option[Int]) = (Some(1),Some(2),Some(3))
Upvotes: 7
Reputation: 15141
Yes shapeless can do a lot!
import shapeless._
import syntax.std.tuple._
trait basicOption extends Poly1 {
implicit def default[T] = at[T](t => Some(t))
}
object fullOption extends basicOption {
implicit def caseSome[T] = at[Some[T]](s => s)
implicit def caseNone = at[None.type](s => s)
}
println((Some(1),2,Some(3)).map(fullOption)) // (Some(1),Some(2),Some(3))
println((Some(1),2,None).map(fullOption)) // (Some(1), Some(2), None)
For more examples you can check their github repo
This is for Shapeless 2.0 and up, if you are using something older you can still do it but instead of calling map
on the tuple directly you would have to go through a HList
.
Upvotes: 6