Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Fabio Labella
@SystemFw
not in that shape, no. What's the larger problem?
Alexander Van Hecke
@alexandervanhecke
I have an F which is a MonadState and I need to implement a function that returns an F[List[Byte] => List[String]]. The returned function should take the bytes, store them in the state and return some value (here a List[String]). I got as far as an F[List[Byte] => F[List[String]]], but need a way to flatten out the second F effect
Fabio Labella
@SystemFw

need to have something that returns an F[List[Byte] => List[String]]

that's the wrong type for your operation

you need List[Byte] => F[List[String]]
the type F[List[Byte] => List[String]] does not let you do the operation that you want
(this is related to the difference between Applicative and Monad btw)
Alexander Van Hecke
@alexandervanhecke
ah excellent suggestion ... let me see if I can make that work. thanks!
Fabio Labella
@SystemFw
let me know if you want to know why that type is incorrect
Alexander Van Hecke
@alexandervanhecke
yes, I'm all ears
Fabio Labella
@SystemFw
so, one of the intuitions for purely functional effects (which is incorrect), is that you have functions that return results and additionally do some effects which appear in the type
instead, you have functions which returns programs, which in turn represent the execution of some effects
e.g def foo(s: String): IO[Int] is not a function that takes a String, returns an Int, and does some IO
it's a function that takes a String and returns an IO[Int] program, which in turn represents the eventual production of an Int + some effects
the other concept is that A => B means that B depends on A
so, in your case, State[Something, List[Byte] => List[String]] represents a program which return a functions List[Byte] => List[String]
but because you want to store the bytes in the state
there has to be a dependency between the thing that can express "input" (list of bytes) and the thing that can express "put in the state", i.e. the F
so you have to have A => F[Something]
if you do F[A => B] there is no way for the state do depend on A (literally the shape does not allow it)
Alexander Van Hecke
@alexandervanhecke
indeed you are right ... thanks for writing that down for me
Fabio Labella
@SystemFw
eventually it's going to be become evident when you are asking for an impossible type :)
another way to look at it is that if you could take an A => F[B] and make it into an F[A => B], you could take any Monad and express it via Applicative instead, and therefore Monad would have no reason to exist
given:
map: (A => B) => F[A] => F[B]
ap  :  F[A  => B] => F[A] => F[B]
flatMap:  (A => F[B)) => F[A] => F[B]
monad is adding that "dependence"
Alexander Van Hecke
@alexandervanhecke
:+1: I wasn't thinking straight ... being Monday morning and all :)
Oleg Pyzhcov
@oleg-py
For intuition, I find it helpful to "read" the types left-to-right, threating [...] as parentheses
val readFileContents: String => IO[Array[Byte]] // given a string, do some IO, return array of bytes.
// vs
val readFileContents_?: IO[String => Array[Byte]] // do some IO, return a function, that when given a string will, without any more IO, give bytes out.
bblfish
@bblfish:matrix.org
[m]
It helps to understand the duality between algebras and coalgebras.
(Free) Algebras give you a Program that does effects such as IO.
Coalgebras are what execute that program, by a sequence of state changes.
bblfish
@bblfish:matrix.org
[m]
:point_up: Edit: It helps to understand the duality between algebras and coalgebras.
(Free) Algebras give you a Program that does or rather describes effects such as IO.
Coalgebras are what execute that program, by a sequence of state changes.
:point_up: Edit: It helps to understand the duality between algebras and coalgebras.
(Free) Algebras give you a Program that does or rather describes effects such as IO.
Coalgebras are machines that execute such programs, by a sequence of state changes.
(At least that is what the CoFree Papers I mentioned above seem to be pointing to -- the coalgebra as machine si pretty well established)
bblfish
@bblfish:matrix.org
[m]
There is one interesting feature of Free is that it is easy to put together a DSL and try out if it gives one what is needed by building out a really simple interpreter (based on hashmaps say). So I'll try that :-)
Greg Fisher
@gnfisher
I'm getting into some trouble with implicits, cats, and doobie... I am unsure how to start to approach this:
 both value AsyncConnectionIO in object connection of type => cats.effect.Async[doobie.free.connection.ConnectionIO]
 and method catsFreeMonadForFree in class FreeInstances of type [S[_]]=> cats.Monad[[β$21$]cats.free.Free[S,β$21$]]
 match expected type cats.Functor[[x]doobie.ConnectionIO[x]]
  def reportMissingPart: Pipe[
    ConnectionIO,
    PriceBookEntry.Salesforce,
    PriceBookEntry.Salesforce
  ] = _.chunks.evalTap { chunk =>
  ...
}
is the function I'm getting the error on.
Oleg Pyzhcov
@oleg-py
@gnfisher using scala 3 by any chance?
oh probably not. You can try doing import doobie.free.connection.AsyncConnectionIO as a temporary fix before anybody with actual doobie experience can help :D
Greg Fisher
@gnfisher
Thanks, i will ask over there -- I wasn't sure if it was doobie or cats specific.
Oleg Pyzhcov
@oleg-py
it's like general implicit resolution thing but I'm pretty sure folks over at doobie have a go-to solution for potential ambiguity added by doobie.
Rob Norris
@tpolecat
You need to import doobie.implicits._
Greg Fisher
@gnfisher
Thanks!
Bob Glamm
@glamm
Is there some magic to enable applicative syntax for a cats-parser Parser? E.g. (foo ~ bar).mapN( (f, b) => ...) ?
Rob Norris
@tpolecat
Hm that should just work. Did you import cats.syntax.all._?
Fabio Labella
@SystemFw
you need to call it on (foo, bar)
or do (foo ~ bar).map { case (a, b) =>
Rob Norris
@tpolecat
Ah, yes. Sorry.
Martijn
@martijnhoekstra:matrix.org
[m]
I suppose in scala 3 we can just use flat tuples instead of those nested things.
As long as you still have the nested ones to deal with, a ~ extractor is nice.
Fabio Labella
@SystemFw
I'd like to explore to what extent mapN is needed in scala 3 yeah
associativity of tuples and different between tuples and parameter lists is the only reason it's there
Bob Glamm
@glamm
ok, that makes sense for a 2-tuple. Is there any way to make it less terrible for a 4-tuple? Right now I have (foo ~ bar ~ baz ~ quux).map { case (((a, b), c), d) => .. }
Fabio Labella
@SystemFw
well, have you tried (foo, bar, baz, quux).mapN
Bob Glamm
@glamm
No luck, but (1, 2).mapN(_ + _) fails in my Ammonite REPL as well. I do have cats.syntax.all._ imported