Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
bblfish
@bblfish:matrix.org
[m]
It should also be flexible so that I can provide serialisation for akka http header fields, or for other frameworks if needed. (In case they don't provide the right output).
(I should be using circe at some point later for parsing JSON. Actually I want to write a streaming non-blocking JSON-LD parser at some point)
Ethan
@esuntag:matrix.org
[m]
I'm not sure if there is some specific library to help with the headers (perhaps an HTTP4S component?), although if you're already looking at Show you can just throw together your own HttpEncoder typeclass with similar functionality pretty easily
bblfish
@bblfish:matrix.org
[m]
ok. I'll study how it works a bit more carefully.
Ethan
@esuntag:matrix.org
[m]
"streaming non-blocking json parser" sounds exactly like what fs2+circe gives you out of the box. I'm not sure how much complexity the LD adds
bblfish
@bblfish:matrix.org
[m]
probably not that much. IT would be an extra layer one would have to build on top I guess, to re-interpret the JSON in terms of RDF Quads.
It hope it will turn out to be that easy :-)
Rob Norris
@tpolecat
Show is not very useful. It can keep you from inadvertently calling toString on things that have no toString, but that's it. In our codebase toString is always and only for debugging and Show always does the same thing as toString. If you need a domain-specific stringability I recommend defining your own typeclass for it.
bblfish
@bblfish:matrix.org
[m]
Following the pattern of cats.Show I wrote up this in Scala3 https://github.com/co-operating-systems/Reactive-SoLiD/blob/master/src/main/scala/run/cosy/http/headers/Rfc8941.scala#L135 . One could make it more efficient by using Rope or something like that, as scalaz does. But I can get to that later.
zeroexcuses
@zeroexcuses
news
Ross A. Baker
@rossabaker
As I recall, the constant factors on Cord or Rope are ghastly, and you had to be assembling a lot before it was better than the dreaded String concat. And then at that scale, you'd be better off with a StringBuilder if you could hide the mutation. I tried to use it a few times, and it's clever, but I could never find a place that it was the best option.
zeroexcuses
@zeroexcuses
besides, 'jvm', what are the biggest differences of OCaml vsScala ?
bblfish
@bblfish:matrix.org
[m]
Is there a typesafe ascii string type? For formatting http headers?
Michael Ahlers
@michaelahlers
@bblfish, if there isn’t already there can be. Check out https://github.com/fthomas/refined.
bblfish
@bblfish:matrix.org
[m]
Thanks @michaelahlers I had come across that but could not remember where. Are they going to have trouble moving to Scala3 given the use of macros?
Michael Ahlers
@michaelahlers
I can’t answer that, and—while not a long-term solution—Refined is cross-compiled against 2.13, which Scala 3 can depend on. See section “The Scala 2.13 TASTy Reader” from https://scalacenter.github.io/scala-3-migration-guide/docs/general/compatibility.html.
Oops, I have that reference backwards. 😅
bblfish
@bblfish:matrix.org
[m]
yes. It looks very interesting.
Michael Ahlers
@michaelahlers
The section right before it.
bblfish
@bblfish:matrix.org
[m]
I know. My own library banana-rdf is having trouble moving to Scala3 because of the removal of type projections. https://github.com/lampepfl/dotty-feature-requests/issues/14#issuecomment-815928271
bblfish
@bblfish:matrix.org
[m]
Though that covers a lot more, not just strings...
Adam Rosien
@arosien
@bblfish:matrix.org there's https://github.com/typelevel/case-insensitive, which i think might be useful for headers, since @rossabaker wrote it
but i can't remember the RFC anymore
Ross A. Baker
@rossabaker
case-insensitive was written for http4s, and used in its modeled headers, but can represent characters that are illegal in headers.
bblfish
@bblfish:matrix.org
[m]
Ah yes, I saw that one be used by http4s :-)
Ross A. Baker
@rossabaker
I've thought about tightening those headers down to make illegal states unrepresentable, but haven't figured it out without making the library unusable.
Refined is probably the closest.
A lot of things you can handle by storing Plain Old Strings and encoding/decoding them. Unfortunately, there's no standard way to encode several codepoints into an HTTP header. You're dealing with a restricted alphabet.
Even ASCII doesn't get you out of the mess, because most (all?) control characters are forbidden.
You could use something like Literally to validate literals. It's a macro soution, but works on Scala 2 and Scala 3.
But anytime you're accepting things from the wire, or doing anything dynamic, that error type is going to be a big nuisance for limited benefit, and we don't like to throw.
Alexander Van Hecke
@alexandervanhecke
is there a way to let cats-parse consume an fs2.Stream[F, Byte] or an InputStream instead of a String?
I have a zip file full of files I need to parse in one go, I first read all the files to Strings and concatenate those before passing it to my parser. doing it directly from stream would be nice
Ross A. Baker
@rossabaker
I think the answer is no: incremental parsing is a lot more complicated, and I don't remember cats-parse supporting it. But there's a dedicated cats-parse Gitter, where perhaps there's better news.
bblfish
@bblfish:matrix.org
[m]
What I am doing (provisionally) is to create a case class FsString private (chars: Seq[Char]) which can only be built by cats.parse or by a constructor in the object that does the verification of the content first. That should give me enough type safety for the moment. (Good to know about Literally).
bernardopinto
@bernardopinto

Hi tere,
I'm exploring how cats does type conversion, in this specific case, Either => EitherOps conversion.
I've tracked up to EitherSyntax that implements an implicit def catsSyntaxEither converting an Either => EitherOps.
However I don't get where/how the conversion is summoned. I would expect some implicit class to allow infix notation to do
something like Right().bimap(leftChannel, rightChannel).
either syntax

Would appreciate any help :)

Rob Norris
@tpolecat
The conversion is typically in scope via the import of cats.syntax.all._
@ cats.syntax.all.catsSyntaxEither(Right()) 
res3: cats.syntax.EitherOps[Nothing, Unit] = cats.syntax.EitherOps@f29f2af0
Maybe I don't understand your question.
Luis Miguel Mejía Suárez
@BalmungSan
@bernardopinto do you know that an implicit class is just sugar syntax for a class and an implicit def (implicit conversion)?
That is why they can not be top-level and why libraries like cats don't use them but rather just have normal class and the conversions in some traits that are shared.
Does that answer your question? Or did I misunderstood it?
Adam Rosien
@arosien

What I am doing (provisionally) is to create a case class FsString private (chars: Seq[Char]) which can only be built by cats.parse or by a constructor in the object that does the verification of the content first. That should give me enough type safety for the moment. (Good to know about Literally).

@bblfish:matrix.org you may know already, but refined automates that stuff. there may be other "newtype"-like support that removes the tagged type approach of refined

bblfish
@bblfish:matrix.org
[m]
bernardopinto
@bernardopinto
@BalmungSan I actually didn't know that.
But in cats.syntax.either the final class EitherOps does not extends EitherSyntax. And in EitherSyntax is where catsSyntaxEither (Either => EitherOps) lives. So I'm not sure how that connection happens.
Also @tpolecat how does cats gets from a Right(value): Either[E, A] => Bifunctor[Either] just by importing import cats.syntax.either._ and calling Right(value).bimap(ec, vc)?
I have an example here: https://github.com/bernardopinto/ammonite-scripts/blob/master/BifunctorStudy.sc
Luis Miguel Mejía Suárez
@BalmungSan

@bernardopinto
Ok, let's try to go step by step in more or less the way the compiler does.

Given:

import cats.syntax.all._
val either: Either[E, A] = Right(value)
either.bimap(ec, vc)

The compiler sees a call to bimap on a value of type Either[E, A], the type Either[E, A] doesn't have such a method so the compiler tries to search for implicit conversion from Either[E, A] into anything that has a bimap method with the correct signature; remember it has a limited scope from where it searches.

In this case, it will eventually search in the lexical scope, i.e., in whatever is imported.
The line import cats.syntax.all._ imports an implicit conversion from Either into EitherOps which does has such bimap method.
But, how does that import provided that extension?

You can see that conversion defined here inside the EitherSyntax trait.
Then here we can see that the AllSyntax trait extends the EitherSyntax one.
And finally here you can see that the all object extends the AllSyntax trait; thus having inside it the implicit conversion.
Which is ultimately put in scope with the import

bernardopinto
@bernardopinto
@BalmungSan alright got it thanks :)
I was not familiar with regular use of type conversions like this. But it makes sense now, goes back to what you said about having an implicit def and a case class.
Luis Miguel Mejía Suárez
@BalmungSan
@bernardopinto note is not a case class, is a value class. You do not want the class that contains the extension methods to really exists.
bernardopinto
@bernardopinto
@BalmungSan true, mental typo. Thanks for the help :)
Luis Miguel Mejía Suárez
@BalmungSan
You are welcome :)
Adam Rosien
@arosien
i usually think of it like:
case class Foo(s: String)

implicit class FooOps(foo: Foo) extends AnyVal {
  def hello(): String = s"Hello $foo.s!"
}
val foo = Foo("Luis")

- foo.hello() // the compiler replaces this code with the following
+ new FooOps(foo).hello() // since FooOps is a value class, no FooOps actually gets instantiated