Version: 2022.03.02
Think of all the arguments you've heard as to why static typing is desirable — every single one of those arguments applies equally well to using types to represent error conditions.
An odd thing I’ve observed about the Scala community is how many of its members believe that a) a language with a sophisticated static type system is very valuable; and b) that using types for error handling is basically a waste of time. If static types are useful—and if you like Scala, presumably you think they are—then using them to represent error conditions is also useful.
Here's a little secret of functional programming: errors aren't some special thing that operate under a different set of rules to everything else. Yes, there are a set of common patterns we group under the loose heading "error handling", but fundamentally we're just dealing with more values. Values that can have types associated with them. There's absolutely no reason why the benefits of static ty
You mention that you would only use circe auto derivation in only a few limited cases - may I ask why? It looks like you are using semi-auto derivation instead. Why is this better/more stable?
The difference is where the derivation happens - in semiauto, you only have one place where a codec for a given type will be derived: at definition site, which is usually the companion object (it's the companion object in our case, but it could be anywhere really - point still stands that it's easier to track). In auto derivation, codecs are derived as needed by the usage - e.g. in the endpoint definitions or in a controller (depending on the tech stack you use). The problem here is that you need all the codecs of all the fields and all their fields (...and so on...) to be available there.
The centralization of the codecs in Semiauto mode allows us to switch to a different format at any time, while keeping the representation consistent across all usages of it. Additionally, it allows us to test the codec logic witho
I'm going to do something that I don't normally do, which is to say I'm going to talk about comparative benchmarks. In general, I try to confine performance discussion to absolute metrics as much as possible, or comparisons to other well-defined neutral reference points. This is precisely why Cats Effect's readme mentions a comparison to a fixed thread pool, rather doing comparisons with other asynchronous runtimes like Akka or ZIO. Comparisons in general devolve very quickly into emotional marketing.
But, just once, today we're going to talk about the emotional marketing. In particular, we're going to look at Cats Effect 3 and ZIO 2. Now, for context, as of this writing ZIO 2 has released their first milestone; they have not released a final 2.0 version. This implies straight off the bat that we're comparing apples to oranges a bit, since Cats Effect 3 has been out and in production for months. However, there has been a post going around which cites various compar
package example | |
object RecMap { | |
object Record { | |
// use this scope to bound who can see inside the opaque type | |
opaque type Rec[A <: Tuple] = Map[String, Any] | |
object Rec { | |
type HasKey[A <: Tuple, K] = |
Fibers are an abstraction over sequential computation, similar to threads but at a higher level. There are two ways to think about this model: by example, and abstractly from first principles. We'll start with the example.
(credit here is very much due to Fabio Labella, who's incredible Scala World talk describes these ideas far better than I can)
Consider the following three functions
At the beginning of 2030, I found this essay in my archives. From what I know today, I think it was very insightful at the moment of writing. And I feel it should be published because it can teach us, Rust developers, how to prevent that sad story from happening again.
What killed Haskell, could kill Rust, too
What killed Haskell, could kill Rust, too. Why would I even mention Haskell in this context? Well, Haskell and Rust are deeply related. Not because Rust is Haskell without HKTs. (Some of you know what that means, and the rest of you will wonder for a very long time). Much of the style of Rust is similar in many ways to the style of Haskell. In some sense Rust is a reincarnation of Haskell, with a little bit of C-ish like syntax, a very small amount.
Is Haskell dead?
import java.sql.Types | |
import io.circe._ | |
import io.getquill.context.jdbc.JdbcContextBase | |
import org.postgresql.util.PGobject | |
import doobie._ | |
import doobie.implicits._ | |
import doobie.postgres.implicits._ | |
sealed trait IdentifierType |
See also List of materials about Software Design in Haskell
Junior | Middle | Senior | Architect | |
---|---|---|---|---|
Haskell level | Basic Haskell | Intermediate Haskell | Advanced Haskell | Language-agnostic |
Haskell knowledge scope | Learn you a Haskell | Get programming with Haskell | Haskell in Depth | Knows several languages from different categories |
Get programming with Haskell | Haskell in Depth | Functional Design and Architecture | ||
Soar with Haskell | [Soar |
import fs2.{Chunk, Stream, Pull} | |
import cats.collections.Heap | |
import cats.implicits._ | |
object SortMerge { | |
def sortMerge[F[_], A: Ordering](streams: List[Stream[F, A]]): Stream[F, A] = { | |
implicit val ord: cats.Order[Stream.StepLeg[F, A]] = | |
new cats.Order[Stream.StepLeg[F, A]] { | |
val ordA = implicitly[Ordering[A]] |