Skip to content

Instantly share code, notes, and snippets.

View blouerat's full-sized avatar

Bastien Louërat blouerat

View GitHub Profile
def retry[F[_]: Monad, E, A](f: => EitherT[F, E, A])(n: Int): EitherT[F, List[E], A] =
Stream.fill(n)(f).traverseU(_.swap).map(_.toList).swap
@blouerat
blouerat / magic_applicative.md
Created April 27, 2015 14:53
Monad, Applicative & Json

Say we have a morally correct json library.

It comes with types like: JValue, JObject and Path.

It also has error types extending JsonError like ParsingError, CastingError and FieldError. To make it even smarter, there's a sweet Semigroup[JsonError] to accumulate errors properly (left as an exercise).

Finally, there are a bunch of basic combinators:

def parse(in: String): ParsingError \/ JValue
@blouerat
blouerat / magic_applicative_2.scala
Created April 29, 2015 11:56
Monad, Applicative & Json 2
object jsonExample {
import scala.language.higherKinds
import scalaz._, Scalaz._
type Path = String
type JValue
type JObject
implicit class RichDisjunction[A, B](disjunction: A \/ B) {
trait HasInverse[A]
object HasInverse {
def apply[A]: HasInverse[A] = new HasInverse[A] {}
}
implicit def dummyHasInverse[A]: HasInverse[A] = HasInverse[A]
trait Inverse[A, B] { self =>
def value: A
def inverse: B
@blouerat
blouerat / foldMapF.scala
Created September 3, 2015 11:04
OptionT.foldMapF
def foldMapF[F[_]: Monad, A, B](o: OptionT[F, A], f: A => B)(implicit M0: Monoid[B]): F[B] = o.fold(f, M0.zero)
@blouerat
blouerat / etc.scala
Created August 8, 2022 15:07
The "Etc/GMT+3" time zone ID actually refers to "-03:00", as demonstrated here
import java.time.ZoneId
import java.time.format.DateTimeFormatterBuilder
import java.time.temporal.TemporalQueries
def parseZoneId(input: String): ZoneId =
new DateTimeFormatterBuilder()
.appendZoneId
.toFormatter
.parse(input)
.query(TemporalQueries.zoneId)