Next stop: type lambdas and partially applied types, which I personally still find hard to grasp. Some people refer to type constructors as types with holes you need to fill to get a well formed type. As you mentioned lifting functions mentally to the type level can help understand the concepts. What I found interesting about generics and generic functions in particular is that they limit the possible implementations and help alot when it comes to reasoning by only looking at the types.
Thank you Daniel, this is very crisp and clear , however I'm just wondering for Option[Seq[]] , why my code is not compiling It is something like trait CustomContainer[F[C[_]]] { def filterByQueryParameters[A, B](container: F[A])(f: A => B): F[B] } But this is not working for Option[Seq[CaseClass]], could you please spot what I'm missiing here. Thanks
So, considering an Option[+A] - where I can create an Option[List[Int]], would it be correct that Option[+A] is only a level 1 type because the API of Option never interacts with the inner type?
Hi Daniel, Thanks a lot for the nice video. I am confused about a particular scenario, I have tried to summarize the scenario in dummy code( it does not compile). Could you please help me understand how can the scenario be achieved? trait GenericFlatten[F[G[T]]]{ // sample concrete type List[Set[Int]] or Seq[List[String]] def flatten(input: F[G[T]]): F[T] // F[G[T]] => List[Set[Int]] , F[T] => List[Int] }
Awesome video! Almost a super power of explaining complex abstract stuff in simple words :) One question to clarify: when you defined functorList as new Functor[List] that became level-1 type or level-0 type?
I think they call it proper type or value type but I like your level scheme more intuitive. If you need a good reading before going to sleep 😬 scala-lang.org/files/archive/spec/2.13/03-types.html
Next stop: type lambdas and partially applied types, which I personally still find hard to grasp. Some people refer to type constructors as types with holes you need to fill to get a well formed type. As you mentioned lifting functions mentally to the type level can help understand the concepts. What I found interesting about generics and generic functions in particular is that they limit the possible implementations and help alot when it comes to reasoning by only looking at the types.
Yep - type lambdas coming in the next video tomorrow!
Superb explanation! Thank you!
Great explanation!
Thank you Daniel, this is very crisp and clear , however I'm just wondering for
Option[Seq[]] , why my code is not compiling
It is something like
trait CustomContainer[F[C[_]]] {
def filterByQueryParameters[A, B](container: F[A])(f: A => B): F[B]
}
But this is not working for Option[Seq[CaseClass]], could you please spot what I'm missiing here. Thanks
Really good videos. Super clear, super detailed.
Glad to hear it!
Thank you for all of your Scala videos, I am learning a lot from them :-)
Glad they're useful!
So, considering an Option[+A] - where I can create an Option[List[Int]], would it be correct that Option[+A] is only a level 1 type because the API of Option never interacts with the inner type?
It's a "level-1" type in the video, yes - not sure what you mean by "never interacts with the inner type".
@@rockthejvm Thank you. I mean that no method on Option will need to call any method on the Int, only the List
What an incredible explanation thank you
Happy it clicked!
Hi Daniel,
Thanks a lot for the nice video.
I am confused about a particular scenario, I have tried to summarize the scenario in dummy code( it does not compile). Could you please help me understand how can the scenario be achieved?
trait GenericFlatten[F[G[T]]]{ // sample concrete type List[Set[Int]] or Seq[List[String]]
def flatten(input: F[G[T]]): F[T]
// F[G[T]] => List[Set[Int]] , F[T] => List[Int]
}
implicit object GenericFlattenListSetInt extends GenericFlatten[List[Set[Int]]]{
override def flatten(input: List[Set[Int]]): List[Int] = input.flatMap(_.toList)
}
def getFlattenCollection[F[G[T]]](input : F[G[T]])(implicit gf : GenericFlatten[F[G[T]]]): F[T] ={
gf.flatten(input)
}
val listOfSet: List[Set[Int]] = List(Set(1,2), Set(2,3))
val flattenList = getFlattenCollection(listOfSet)
// expected output is 1,2,2,3
Hi Imran, it's certainly possible, only that you can't pass all the type arguments nested like that. You can do this:
trait GenericFlatten[F[_], G[_], T] {
def flatten(input: F[G[T]]): F[T]
}
implicit object GenericFlattenListSetInt extends GenericFlatten[List, Set, Int]{
override def flatten(input: List[Set[Int]]) = input.flatMap(_.toList)
}
def getFlattenCollection[F[_], G[_], T](input : F[G[T]])(implicit gf : GenericFlatten[F, G, T]): F[T] ={
gf.flatten(input)
}
@@rockthejvm Thank you very much, Daniel.
I loved this explanation
Glad you liked it!
Awesome video! Almost a super power of explaining complex abstract stuff in simple words :)
One question to clarify: when you defined functorList as new Functor[List] that became level-1 type or level-0 type?
If you can attach it to a value, that's a level-0 type in this terminology.
I think they call it proper type or value type but I like your level scheme more intuitive. If you need a good reading before going to sleep 😬 scala-lang.org/files/archive/spec/2.13/03-types.html
Can you put out a video that explains the placeholder ? or * for higher kind types as supposed to _? Thanks for the video
Those placeholders will probably not be needed too much now with proper type lambda syntax in Scala 3 th-cam.com/video/b1C8ybLpzUc/w-d-xo.html
Amazing video, thank you very much!!
Glad you liked it!
Very nice video, waiting next :)
Great explanation! can you explain in other videos on shapeless?
Noted - will have something on shapeless as well
What would be awesome is to give code examples where a higher level type can simplify a codebase
A subject for some 2-hour video! This would require some longer-form tutorial.
Good description but you might want to show what you can actually do with something like your functorList.
Thank you for the video and light theme in IDE :)
I find the light theme much easier to read. Thanks.
HashMap - why not just call it Dict? 🙂