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
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
mmm, I guess those need to be effects for mapN to work, one second
yeah, (List(1), List(3)).mapN(_ + _) works as expected in my REPL. Hmmm
aha, bitten by overlapping imports. Had to remove cats.implicits._. Sorry about that :/
voropaevp
@voropaevp
Is it a good idea to put validators inside the constructors?

  case class InstrumentError(error: String)

  type ValidInstrumentPart[A] = ValidatedNel[InstrumentError, A]

sealed trait MdSide

object MdSide {
  def parse(side: String): ValidInstrumentPart[MdSide] = side match {
    case "bid" => Bid().validNel
    case "ask" => Ask().validNel
    case _ => InstrumentError(s"[$side] unsupported").invalidNel
  }
}

sealed case class Bid() extends MdSide

sealed case class Ask() extends MdSide
It makes it a little awkward type later, when I need to construct another class from it
object MdInstrument {
  def fromValidated(tickerV: ValidInstrumentPart[Ticker], sideV[MdSide])...
Luis Miguel Mejía Suárez
@BalmungSan
@voropaevp not sure what you mean.
There are no validators inside constructors in your code.
voropaevp
@voropaevp
@BalmungSan I mean parsers that return validatedNel
Luis Miguel Mejía Suárez
@BalmungSan
That seems good to me.
But again, I really did not understand your question.
voropaevp
@voropaevp
docs for Validated suggest writing a typeclass for parsing
trait Parser[A] {
  def parse(s: String): ValidInstrumentPart[A]
}

object Parser{
  def apply[A](implicit A: Parser[A]): Parser[A] = A

  implicit val mdSideParser: Parser[MdSide] =
    new Parser[MdSide] { def parse(s: String): ValidInstrumentPart[MdSide] = ... }
}