Where communities thrive

  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
Repo info
  • 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
With you so far.
Fabio Labella
so it emits programs, but doesn't execute them, which btw is useful sometimes! The point of the paradigm is all about being able to juggle doing (execute this now), with being (use this effect as a value, which gets executed "later")
Maybe I am being as thick as a whale omlette but this "it emits programs, but doesn't execute them" is baffling me. What prevents map from executing them?
Fabio Labella
btw I think it's easier if you focus on IO first, because with Stream you have two types at play (Stream and IO), which I think is confusing
look at IO first
map has no idea that what you return is a program
just think about IO for a minute
the type is map[A, B]: IO[A] => (A => B) => IO[B]
IO is a datatype, which gets interpreted
and map is fully parametric on A and B
so you cannot use a characteristic of B to do special things
but you are saying for some special Bs, i.e. B = IO[C] , you want to do something else
instead, when you do ioA.map(printEffect), it gets treated as any other B, i.e. you get IO[IO[Unit]]
Struggling with "you cannot use a characteristic of B to do special things".
Fabio Labella
let's do this
let's implement a small language
a mini Console IO
ah ok, parametricity
we can look at that then
have you heard the term before?
Yes I have a vague notion but not enough to explain it to another person.
Fabio Labella
yeah I don't mean a formal one
the general idea is that you're fully abstract with respect to type parameters, i.e. you have to do the same thing for all instances of them
Yes, that's simple.
Fabio Labella
say for example def identity[A](a: A): A = a
without cheating (asInstanceOf, nontermination, etc)
parametricity restricts the state space of possible implementations, and it's a big reason for the "if it compiles it works" meme (which obviously isn't strictly true, but it hints at the reduction of the solution space that types give you)
so, parametricity is a good thing
Fabio Labella
but that means that you can't do, if you care about it, this thing
def identity[A](a: A): A = 
  if (a.isInstanceOf[Int]) (a.asInstanceOf[Int] + 1).asInstanceOf[A] else a
does that also make sense?
as to why you don't want to do that?
Crystal is opaque by comparison.
Fabio Labella
if (a.isInt) a + 1 (with automatic casting)
is not the the code is dirty, is that now identity suffers from all the problems of identity: Int => Int
i.e the types stopped helping you in restricting the solution space
anyway, that is not desirable
does that make sense?
Absolutely no issues so far.
Fabio Labella
ok, so let's try building a super dumb IO
without even datatype and interpreter
and no exception handling either (let alone concurrency and all the things that real IO has)
just a referentially transparent representation of synchronous side effects

I guess what I am struggling with is if map is defined as:

map[A, B]: IO[A] => (A => B) => IO[B]

and flatMap as

flatMap[A, B]: IO[A] => (A => F[B]) => IO[B]

if they both result in IO[B] then why does one necessarily run a program and one does not?

Fabio Labella
you need to look at the type of the function being passed in
also, you have to have IO in A => IO[B] in flatMap, not F
Typo, sorry.