flatMap with Shapeless yield FlatMapper not found - scala

I'm trying to define some structure like this
case class Transformer[From, To](
name: String,
get: PaymentEvent => From,
to: From => To
I want to filter elements with names that are part of a Set
class filterName(names: Set[String]) extends lowPriority {
implicit def get[From, To] = at[Transformer[From, To]]{ trans =>
if (names.contains(trans.name))
trans :: HNil
else
HNil
}
}
This is the concrete value:
type HTransformer = Transformer[String, String] :: Transformer[Long, Long] :: HNil
When I want to apply the function to the value
private def filter(fields: HTransformer, names: Set[String]): HTransformer = {
fields.flatMap(new filterName(names))
}
The compiler reports errors:
Error:(42, 19) could not find implicit value for parameter mapper: shapeless.ops.hlist.FlatMapper[f.type,shapeless.::[com.ingenico.datalake.Transformer[String,String],shapeless.::[com.ingenico.datalake.Transformer[Long,Long],shapeless.HNil]]]
fields.flatMap(new filterName(names))

I guess you misunderstand type-level calculations.
If you want to filter an hlist depending on whether an element is a part of the Set then you must know this (if an element is a part of the Set) at compile time but actually you know this only at runtime. So filterName will not work.
For example you can transform the hlist to a list and filter it as an ordinary collection at runtime.

Related

Function that retrieves element from HList (while preserving its type)

I have this type which will be generated via shapeless:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
Basically I have a bunch of case objects extending a trait so I managed to create a method which gives me instances of all case objects as an HList
Then using import shapeless.ops.hlist.Last and init I wrote a method to retrieve one of the nodes in the HList if the value is equal to the string "student":
def getLast(hl:hlistt) = {
val last0=Last[hlistt]
val la=last0(hl)
if (la.value == "student") la
else init(hl)
}
The issue is that if I call this method I will not get the correct node type from the HList.
getLast(STUDENT :: AUTO_LOANS :: HNil)
The method works and returns the node but the type is off:
Product with Serializable = STUDENT :: HNil
Do I need some Witness/Aux implicits to return the correct type?
la is of type AUTO_LOANS.type, init(hl) is of type STUDENT.type :: HNil, so
if (la.value == "student") la
else init(hl)
is of type Any (or Product with Serializable).
If you would like to return values of different types from different branches you need a Poly.
import shapeless.{Poly1, Witness}
object myPoly extends Poly1 {
implicit def studentCase: Case.Aux[Witness.`"student"`.T, STUDENT.type] =
at(_ => STUDENT)
implicit def autoLoansCase: Case.Aux[Witness.`"auto-loans"`.T, AUTO_LOANS.type] =
at(_ => AUTO_LOANS)
}
import shapeless.syntax.singleton._
println(
myPoly("student".narrow)
) // STUDENT
println(
myPoly("auto-loans".narrow)
) // AUTO_LOANS
// println(
// myPoly("abc".narrow)
// ) // doesn't compile
This approach works if the string is known at compile time.
I am not quite sure what you want to do. Given:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
Last[hlistt] will resolve to AUTO_LOANS.type (your true if branch)
while init will resolve to STUDENT :: HNil (your false if branch)
the LUB (least upper bound) of these types will be Product with Serializable so that's why you see that.
If you want to check a runtime property of a member of the hlist you'll have to thread the appropriate typebounds and result types through by deriving them with the appropriate machinery. In this case that is already given by shapeless.
https://scalafiddle.io/sf/fdtn3cz/0
Is this what you wanted?
EDIT:
I also just read
I have this type which will be generated dynamically:
what do you exactly mean by "dynamically"? because unless you can specify some compile time properties, shapeless might not be the solution you're looking for.

List of classes implementing a certain typeclass

I would like to define a List of elements implementing a common type class. E.g.
trait Show[A] {
def show(a: A): String
}
implicit val intCanShow: Show[Int] = new Show[Int] {
def show(int: Int): String = s"int $int"
}
implicit val stringCanShow: Show[String] = new Show[String] {
def show(str: String): String = str
}
The problem is, how to define a list = List(1, "abc") such that it is guaranteed that a Show instance for these values is in scope? I would then like to map this list over show like list map {_.show}.
I will first sketch a solution, and then explain why the naive approach with List[Any](1, "abc") cannot work.
What you can do
Define a wrapper class that can hold instances of type A together with instances of Show[A]:
case class Showable[A](a: A, showInst: Show[A]) {
def show: String = showInst.show(a)
}
Define your list as List[Showable[_]]:
var showableList: List[Showable[_]] = Nil
Maybe define a separate method to fill this list (consider packing the list itself and the builder-method in a class):
def addShowable[A: Show](a: A): Unit = {
showableList ::= Showable[A](a, implicitly[Show[A]])
}
Alternatively, you can carefully add a (very tightly scoped) implicit conversion:
implicit def asShowable[A](a: A)(implicit s: Show[A]): Showable[A] =
Showable(a, s)
and then costruct your list as follows (note the explicit type ascription):
val showableList = List[Showable[_]](1, "abc")
Now you can go through the list and call show:
showableList.map(_.show)
to obtain a list of String.
What you cannot do
You cannot simply define
val list: List[Any] = List(1, "abc", <showable3>, ..., <showableN>)
and then expect to be able to call show, because in order to call Show.show, you need actual Show instances. These things are not some type-hints that can be erased at runtime, they are actual objects, and they must be supplied by the compiler. Once you have created a List[Any], all is lost, because all the types are merged into an unexpressive upper bound Any, and the compiler has no way to inject all the necessary implicits Show[T_1],..., Show[T_N]. The argument is very similar to the third section "Dealing with implicits when defining interpreter for the Free monad" of this lengthy answer of mine.
An alternative way of handling this would be to use the shapeless library.
I would really reccommend this book which explains shapeless in a clear and concise manner.
Shapeless provides two things that I think will help you in this case:
Heterogeneous lists (HList)
Polymorphic functions to enable the HList mapping operation.
First import the required libraries (shapeless):
import shapeless.{HNil, Poly1, ::}
Create a heterogeneous list of whatever types you require. Note the type annotation is only there for clarity.
val data : Int :: String :: HNil = 1 :: "hello" :: HNil
Create a polymorphic function defining an implicit value for every type you require.
object Show extends Poly1 {
implicit def atT[T: Show] = at[T] (implicitly[Show[T]].show)
}
Shapeless provides an extension method for map on a HList to enable applying the show function to every element in the list
val result : String :: String :: HNil = data.map(Show)
Edited: thanks to #dk14 for the suggested improvement to the definition of the Show polymorphic function.
The core problem here is that you want to create a heterogenous list, something like List[Int, String] instead of List[Any]. This means you need a different structure that would preserve Int and String types, but still would be "mappable" like List. The one structure in scala-library that can contain heterogenous types is Tuple:
val tuple = (1, "abc")
val result = List(implicitly[Show[Int]].show(tuple._1), implicitly[Show[Int]].show(tuple._2))
However, scala-library can't map over tuples - you might want some syntax sugar for better readability.
So the obvious solution is HList from Shapeless: Int :: String :: HNil (or you can use tuple ops and stay with (Int, String))
import shapeless._
import poly._
//show is a polymorphic function
//think of it as `T => String` or even `(Show[T], T) => String`
object show extends Poly1 {
implicit def atT[T: Show] = at[T](implicitly[Show[T]].show)
}
# (1 :: "aaaa" :: HNil) map show
res8: String :: String :: HNil = "int 1" :: "aaaa" :: HNil
Or you could use at[Int]/at[String] instead of type-classes, like in #Steve Robinson's answer.
P.S. The lib could be found here. They also provide one-liner to get Ammonite REPL with shapeless integrated, so you could try my example out using:
curl -s https://raw.githubusercontent.com/milessabin/shapeless/master/scripts/try-shapeless.sh | bash
Notes:
Practically Shapeless solution requires as same amount of maintenance as Tuple-based one. This is because you have to keep track of your Int and String types anyways - you can never forget about those (unlike in homogenous List[T] case). All Shapeless does for you is nicer syntax and sometimes better type inference.
If you go with tuples - you can improve readability by using implicit class instead of Haskell-like style, or if you still want Haskell-like, there is a Simulacrum macro for better type-class syntax.
Given that other scala-library-only alternatives just capture type class instances inside some regular class, you could be better off with a regular OOP wrapper class:
trait Showable[T]{def value: T; def show: String}
class IntShow(val value: Int) extends Showable[Int]{..}
class StringShow(val value: String) extends Showable[String] {..}
val showables: List[Showable[_]] = List(new Showable(5), new Showable("aaa"))
showables.map(_.show)
Looks cleaner and more readable to me :)
If you like to rewrite dynamic dispatching in FP-style:
sealed trait Showable
final case class ShowableInt(i: Int) extends Showable
final case class ShowableString(s: String) extends Showable
implicit class ShowableDispatch(s: Showable){
def show = s match{ //use `-Xfatal-warnings` scalac option or http://www.wartremover.org/ to guarantee totality of this function
case ShowableInt(i) => ...
case ShowableString(s) => ...
}
}
List(ShowableInt(5), ShowableString("aaa")).map(_.show)
If you really want static dispatching (or ad-hoc polymorphism), given that other solutions introduce Showable[_] which is practically Showable[Any]:
case class Showable[T](v: T, show: String)
def showable(i: Int) = Showable(i, s"int $i")
def showable(s: String) = Showable(i, s)
List(showable(5), showable("aaa")).map(_.show)
Disclamer: I've made this answer to provide a solution to the concrete development problem, and not the theoretical problem of using typeclass
I would do it this way:
trait Showable{ def show(): String }
implicit class IntCanShow(int: Int) extends Showable {
def show(): String = s"int $int"
}
implicit class StringCanShow(str: String) extends Showable {
def show(): String = str
}
val l: List[Showable] = List(1,"asd")
Note that I changed the meaning of the trait Show, into Showable, such that the implementing classes are used as wrapper. We can thus simply require that we want Showable instances
(and because those classes are implicit, input of the List are automatically wrapped)

How to create a constrained HList from a sequence?

I have a constructor that has the following signature:
class Event[DL <: HList](
detailsIn: DL
)(implicit lbcr: LUBConstraint[DL, EventDetail[_]]) { ...
In the companion object I have:
def apply[DL <: HList](
detailIn: String*
)(implicit lbcr: LUBConstraint[DL, EventDetail[String]]) =
new Event(
if (detailIn.map(deet => EventDetail(deet)).toList.size == 1)
detailIn.map(deet => EventDetail(deet)).toList.toHList[String :: HNil].get
else throw new NotImplementedException()
)(lbcr)
Admittedly, this apply method could be cleaned up.
This yields the following error which I'm frankly lost about how to deal with:
Error:(87, 7) type mismatch;
found : shapeless.LUBConstraint[DL,edu.cornell.ansci.dairy.econ.model.event.EventDetail[String]]
required: shapeless.LUBConstraint[shapeless.::[String,shapeless.HNil],edu.cornell.ansci.dairy.econ.model.event.EventDetail[_]]
The second part of the issue: is there any way to make this polymorphic over the size of detailIn? Based on my other readings, I assume not, and I can think of no way to do it in Scala. The best I can do is to support for convenience a fixed number lengths for detailIn string sequences, and if that is exceeded, the user of the class must use HList directly.
Don't be scared by that type error, it's pretty explicit, let me try to type the body of your apply method bottom up:
At the very bottom you have a String :: HNil:
val e0: String :: HNil = e.toList.toHList[String :: HNil].get
The if doesn't change that:
val e1: String :: HNil =
if (???) e0
else throw new NotImplementedException()
Thus, when you create Event, Event.DL = String :: HNil:
new Event[String :: HNil](e1)(lbcr)
But lbcr has type LUBConstraint[DL, _], that's incompatible with LUBConstraint[String :: HNil, _]!
For the second part of your question, shapeless provides a safer alternative to varargs: ProductArgs. Backed by a macro and a slightly more involved definition, object myfunction extends ProductArgs { def applyProduct[L <: HList](args: L) } instead of def myfunction(args: Any*), you can get your varargs as an HList instead of a Seq[String].

Evidence-preserving LUB constraint for HList

I think I need a HList that is constrained to have all of its elements being a subtype of a certain type. LUBConstraint seems to be what I want, and indeed it does constrain the construction of such a HList - but I can't see how to get the evidence out again, so that I can map (actually, traverse, because it needs to be monadic) over the HList and call a method (that exists in the LUB type) on each of the elements.
In addition, I want the type of the HList resulting from the traverse operation to be exactly the same type as the type of the input HList.
The use case is a kind of functional "listener list" - all of the elements of the HList are "listeners" which must be notified of "events", accept or reject them, and return new versions of themselves with updated "internal state". If that was all I needed, then I could just use an ordinary immutable Scala collection. But I also want direct typed access to individual elements without using asInstanceOf - hence the motivation for trying to use HList.
In general if you have some operation that you want to perform on all of the elements in an HList, you'll want to map a polymorphic function value over the HList. For example, suppose I have the following setup:
trait Listener[L <: Listener[L]] {
def handle(s: String): Option[L]
}
class FooListener extends Listener[FooListener] {
def handle(s: String) =
if (s.size == 3) Some(this) else None
}
class BarListener extends Listener[BarListener ]{
def handle(s: String) = Some(this)
}
import shapeless._
val listeners = new FooListener :: new BarListener :: HNil
Now I want to send a String to each of these listeners and gather the results. If I just wanted to send a fixed value, this would be easy:
object event123 extends Poly1 {
implicit def listener[L <: Listener[L]] = at[L](_.handle("123"))
}
val result = listeners.map(event123)
Which will be appropriately typed as an Option[FooListener] :: Option[BarListener] :: HNil. If I'm using shapeless-contrib, I can sequence this HList:
import scalaz._, Scalaz._, shapeless.contrib.scalaz._
val sequenced: Option[FooListener :: BarListener :: HNil] = sequence(result)
Or just use traverse:
traverse(listeners)(event123)
Unfortunately there are restrictions on how polymorphic function values can be defined that mean that partial application isn't convenient, so if we don't know the String we're sending at compile time, this is a lot more complicated:
object event extends Poly1 {
implicit def listener[L <: Listener[L]] = at[(L, String)] {
case (listener, string) => listener.handle(string)
}
}
traverse(listeners.zip(listeners.mapConst("123")))(event)
Where we've zipped the elements with the string and then mapped a polymorphic function that takes tuples over the result. There are other ways you could do this using more or less the same approach, but none of them are terribly clear.
A completely different approach is just to skip the polymorphic function values and define a new type class:
trait Notifiable[L <: HList] {
def tell(s: String)(l: L): Option[L]
}
object Notifiable {
implicit val hnilNotifiable: Notifiable[HNil] = new Notifiable[HNil] {
def tell(s: String)(l: HNil) = Some(HNil)
}
implicit def hconsNotifiable[H <: Listener[H], T <: HList](implicit
tn: Notifiable[T]
): Notifiable[H :: T] = new Notifiable[H :: T] {
def tell(s: String)(l: H :: T) = for {
h <- l.head.handle(s)
t <- tn.tell(s)(l.tail)
} yield h :: t
}
}
def tell[L <: HList: Notifiable](s: String)(l: L) =
implicitly[Notifiable[L]].tell(s)(l)
And then:
val sequenced: Option[FooListener :: BarListener :: HNil] =
tell("123")(listeners)
This is less generic (it only works on Option, not arbitrary applicatives), but it doesn't require an extra dependency for sequencing, and it's arguably a little less muddled than jumping through hoops to partially apply a polymorphic function value because of weird limitations of the compiler.

Can Map be performed on a Scala HList

I have done a few implementations of HList now. One based on Daniel Spiewak's High Wizardry in the Land of Scala talk and another based on a post in Apocalisp blog. The goal was to have a heterogenous list of which is not heterogenous in the primary type but rather the higher kind. For example:
val requests = Request[String] :: Request[Int] :: HNil
I would be able to do a map across the list to perform the request and result in a heterogenous list of the higher kind. So:
requests.map(execute)
should equal
String :: Int :: HNil
Sadly all my attempts have resulted in an HList of Any. Here is the code from a recent attempt:
class Request[+Out](o:Out) {
type O = Out
def v:O = o
}
object HList {
trait Func[-Elem,Out] {
type Apply[E <: Elem] <: Out
def apply[N <: Elem](e:N):Apply[N]
}
sealed trait HList[Base] {
type Head <: Base
type Tail <: HList[Base]
type Map[Out,F <: Func[Base,Out]] <: HList[Out]
def head:Head
def tail:Tail
def ::[A <: Base](a:A):HList[Base]
def map[Out,F <: Func[Base,Out]](f:F):Map[Out,F]
}
case class HNil[Base]() extends HList[Base] {
type Head = Nothing
type Tail = Nothing
type Map[Out,F <: Func[Base,Out]] = HNil[Out]
def head = error("Head of an empty HList")
def tail = error("Head of an empty HList")
def ::[A <: Base](a:A) = HCons(a,this)
def map[Out,F <: Func[Base,Out]](f:F) = new HNil[Out]
}
case class HCons[Base,A <: Base,B <: HList[Base]](head: A, tail: B) extends HList[Base] {
type Head = A
type Tail = B
type Map[Out,F <: Func[Base,Out]] = HCons[Out,F#Apply[Head],Tail#Map[Out,F]]
def ::[C <: Base](c:C) = HCons(c,this)
def map[Out,F <: Func[Base,Out]](f:F) =
HCons(f(head),tail.map(f))
}
val :: = HCons
}
object Test extends Application {
import HList._
val HNil = new HNil[Request[_]]
val list = new Request[Int](1) :: new Request[String]("1") :: HNil
val (a :: b :: HNil) = list
val y:Request[String] = b
val results = list.map[Any,Unwrap.type](Unwrap)
val i:Int = results.head
}
import HList._
object Unwrap extends Func[Request[Any],Any] {
type Apply[I <: Request[Any]] = I#O
def apply[N <: Request[Any]](e:N) = null.asInstanceOf[Apply[N]]
}
The other attempt was based on the Apocalisp version which uses fold to create a new HList and again it resulted in a HList of Any types. Any tips would be appreciated.
The HList implementation in shapeless is rich enough to subsume both HList and KList functionality. It provides a map operation which applies a higher-ranked function, possibly with type-specific cases, across it's elements yielding an appropriately typed HList result,
import shapeless.Poly._
import shapeless.HList._
// Define a higher-ranked function from Sets to Options
object choose extends (Set ~> Option) {
def default[T](s : Set[T]) = s.headOption
}
// An HList of Sets
val sets = Set(1) :: Set("foo") :: HNil
// Map our choose function across it ...
val opts = sets map choose
// The resulting value
opts == Option(1) :: Option("foo") :: HNil
Note that although it's the case in the above example there's no requirement that the HList elements share a common outer type constructor, it just has to be the case that the higher-ranked function mapped with has cases for all of the types involved,
// size is a higher-ranked function from values of arbitrary type to a 'size'
// which is defined as 1 by default but which has type specific cases for
// Strings and tuples
object size extends (Id ~> Const[Int]#λ) {
def default[T](t : T) = 1
}
implicit def sizeString = size.λ[String](s => s.length)
implicit def sizeTuple[T, U](implicit st : size.λ[T], su : size.λ[U]) =
size.λ[(T, U)](t => 1+size(t._1)+size(t._2))
size(23) == 1 // Default
size("foo") == 3 // Type specific case for Strings
size((23, "foo")) == 5 // Type specific case for tuples
Now let's map this across an HList,
val l = 23 :: true :: "foo" :: ("bar", "wibble") :: HNil
val ls = l map size
ls == 1 :: 1 :: 3 :: 10 :: HNil
In this case the result type of the function being mapped is constant: it's an Int no matter what the argument type is. Consequently the resulting HList has elements all of the same type, which means that it can usefully be converted to a vanilla list,
ls.toList == List(1, 1, 3, 10)
what you need is a Klist with type constructor Request, and a natural transformation execute: Request ~> Id. All of this is detailed in the marvelous type-level programming series of posts at Apocalisp, in particular:
Natural transformation literals
Klist basics
you can checkout the code for the whole series from Mark Harrah's up repo
In your case, you'll need something like
val reqList = new Request[Int](1) :^: new Request[String]("1") :^: KNil
val exec = new (Request ~> Id) { def apply[T](reqs: Request[T]): T = reqs.execute }
val results = reqList down exec
the down method above is conceptually the same as map for a nat transf M ~> Id; you also have more general map which from a nat transf M ~> N and a Klist of kind M yields a KList of kind N.
Note that you have an example of Map with HList in the recent (October 2016, 5 years after the OP) article "Using shapeless' HLists for extra type safety (in Akka Streams)" from Mikołaj Koziarkiewicz.
//glue for the ParserStageDefs
specs.map(s => Flow[Data].map(s.parser).map(s.processor))
.foreach(broadcast ~> _ ~> merge)
The problem lies in the fact that the type information in our specs list is not preserved. Or rather, not preserved the way we want to - the type of the List elements is ParserStageDef[_ >: Int with String], so the lowest common supertype for our decorator and incrementer.
The above implies that, when mapping between the parser and processor elements, the compiler has no way to provide the actual type T that's used within the given spec.
A solution
Here's where HLists come to the rescue. Because they preserve the complete type information for each element, it's possible to define our flow very similarly to our last attempt.
First, let's replace our list with an HList:
import shapeless.ops.hlist._
import shapeless._
//...
val specs = decorator :: incrementer :: HNil
val specsSize = specs.length.toInt
Now, for the mapping from ParserStageDefs into Flows, we need to take a different approach, as the map for HList requires something called P**oly - a polymorphic function value**.
Here's how one would look like in our case:
import shapeless.PolyDefns.~>
object toFlow extends (ParserStageDef ~> ProcessingFlow) {
override def apply[T](f: ParserStageDef[T]) =
Flow[Data].map(f.parser).map(f.processor)
}
For it to work, we'll also have change ProcessingFlow to type ProcessingFlow[_] = Flow[Data, Data, _], since the polymorphic function above expects a higher-kinded type.
Now, our central statement turns out to be:
//we convert to a List[ProcessingFlow[_]] for simplicity
specs.map(toFlow).toList.foreach(broadcast ~> _ ~> merge)
and we're all set!