Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Sep 05 2019 14:43
    @typelevel-bot banned @jdegoes
  • Jan 31 2019 21:17
    codecov-io commented #484
  • Jan 31 2019 21:08
    scala-steward opened #484
  • Jan 31 2019 18:19
    andywhite37 commented #189
  • Jan 31 2019 02:41
    kamilongus starred typelevel/cats-effect
  • Jan 30 2019 00:01
    codecov-io commented #483
  • Jan 29 2019 23:51
    deniszjukow opened #483
  • Jan 29 2019 23:37
  • Jan 29 2019 23:22
  • Jan 29 2019 20:26
    Rui-L starred typelevel/cats-effect
  • Jan 29 2019 18:01
    jdegoes commented #480
  • Jan 29 2019 17:04
    thomaav starred typelevel/cats-effect
  • Jan 28 2019 17:43
    asachdeva starred typelevel/cats-effect
  • Jan 28 2019 07:12
    alexandru commented #480
  • Jan 28 2019 05:45
    codecov-io commented #482
  • Jan 28 2019 05:35
    daron666 opened #482
  • Jan 27 2019 13:56
    codecov-io commented #481
  • Jan 27 2019 13:46
    lrodero opened #481
  • Jan 27 2019 05:47
    codecov-io commented #460
  • Jan 27 2019 05:37
    codecov-io commented #460
Fabio Labella
@SystemFw
def length[F[_], A]](l: F[A]): Int
this is called higher-kinded parametric polymorphism
or in short (and a slight abuse of notation): "higher kinds"
works mostly in conjunction with typeclasses
Steven Fines
@sfines-clgx
the best notation is abused notation
Fabio Labella
@SystemFw
def length[F[_]: Foldable, A]](l: F[A]): Int
that's the real type
so these are the mechanics basically
Steven Fines
@sfines-clgx
the cats Foldable typeclass
Fabio Labella
@SystemFw
yep
trait Foldable[F[_]] { 
  ...
now, on to the pattern
this pattern (which I'm about to show) is part of a class of encodings called final tagless encodings
Steven Fines
@sfines-clgx
ok
Fabio Labella
@SystemFw
so you hear referred as "final tagless"
I have a long explanation on what final tagless means in general, you can look it up at https://systemfw.org/writings
so I'll just explain the actual pattern we use
Steven Fines
@sfines-clgx
bookmarked
Fabio Labella
@SystemFw
which could call "capability traits" or "capability classes" or whatever
the basic idea is that the types that we use for effects, have shape F[_]
this includes IO, primarily
but monad transformer as well
the idea is akin to interface and implementation
Steven Fines
@sfines-clgx
alright
Fabio Labella
@SystemFw
when you have things like
def print(s: String): IO[Unit]
def read: IO[String]

def echo: IO[Unit] = read.flatMap(print)
you want to:
  • describe the domain of effects (just like you use data types to describe the domain of data)
  • have a testable/swappable implementation
  • (additionally, sometimes) increase the generality of echo to be used with many different effects (like a traced IO effect)
and you do it like that
Steven Fines
@sfines-clgx
you would have a trait that defines those in terms of expecting some manner of effect type
Fabio Labella
@SystemFw
trait Console[F[_]] {
  def print(s: String): F[Unit]
  def read: F[String]
}
object Console {
  def apply[F[_]](implicit ev: Console[F]) = ev

  def std: Console[IO] = new Console[IO] {
     def print(s: String): IO[Unit] = ...
     def read: IO[String] = ...
  }
}
then your "programs", like echo are written as
def echo[F[_]: Console: Monad]: F[Unit] = Console[F].read.flatMap(Console[F].print)
Steven Fines
@sfines-clgx
ok
Fabio Labella
@SystemFw
this is achieves all thee goals above, and it composes nicely with other things
e.g. if you have def fetch[F[_]: Cache]: F[User]
you might use them both and get def logic[F[_]: Console: Cache]
then at some point (typically close to main)
you will have
implicit val console = Console.std
implicit val cache = ...


logic[IO]
and "inject" the implementation (or interpret the language, in more FP terms)
this is going to be very nice in scala 3
given Console[IO] = Console.std
...

logic[IO]
Steven Fines
@sfines-clgx
I get the feeling that I will be re-learning scala when scala 3 comes around
Fabio Labella
@SystemFw
also, very often the constructor of things like Console have shape F[Thing[F]] or Resource[F, Thing[F]]
and that's it
it's a way of structuring programs
the OO view is interface + implementation and dependency injection
Steven Fines
@sfines-clgx
ah, k.
I come to this from almost 30 years of OOP
so this is a change
Fabio Labella
@SystemFw
the FP view is that you're constructing a "language" to write your programs in, one that represents your domain in a way that makes the problem you have easy to solve, and then you interpret this language
trait Console[F[_]] this are called "algebras", in the jargon