Skip to content

Instantly share code, notes, and snippets.

View qingwei91's full-sized avatar

Qing qingwei91

View GitHub Profile
import cats.effect._
import scala.concurrent.ExecutionContext.global
// needed to perform logical fork
implicit val cs = IO.contextShift(global)
// an infinite `flatMap` chain as the innerIO always return None
val myIO = retryIfNone(IO(None))
// perform a logical fork using `.start`, this to allow cancellation
@qingwei91
qingwei91 / io-loop.scala
Created December 20, 2019 14:27
Use IO to wrap each loop
import cats.effect._
def retryIfNone(innerIO: IO[Option[Int]]): IO[Int] = {
innerIO.flatMap {
case Some(i) =>
println("something") // used to show some output when testing
IO.pure(i)
case None =>
println("nothing") // used to show some output when testing
retryIfNone(innerIO)
@qingwei91
qingwei91 / naive-loop.scala
Created December 20, 2019 14:26
Loop with termination logic built in
def loop(stopsAfter: Duration) = {
val start: Instant = Instant.now()
while (true) {
if (start.after(stopsAfter) < Instant.now()) {
throw new NonTerminatingError()
} else {
// do your thing
}
}
}
@qingwei91
qingwei91 / gist:f2dfd15765c4250ac457ddfd9a150f79
Created August 20, 2019 16:11 — forked from corvax19/openssh-encrypt-decrypt.txt
Simple text encryption/decryption with openssl
echo -n "That's the text"|openssl enc -e -aes-256-cbc -a
Encrypt with interactive password. Encrypted message is base64-encoded afterwards.
echo -n "That's the text"|openssl enc -e -aes-256-cbc -a -k "MySuperPassword"
Encrypt with specified password. Encrypted message is base64-encoded afterwards.
echo "GVkYiq1b4M/8ZansBC3Jwx/UtGZzlxJPpygyC"|openssl base64 -d|openssl enc -d -aes-256-cbc
Base-64 decode and decrypt message with interactive password.
echo "GVkYiq1b4M/8ZansBC3Jwx/UtGZzlxJPpygyC"|openssl base64 -d|openssl enc -d -aes-256-cbc -k "MySuperPassword"
import $ivy.`io.circe::circe-parser:0.10.0`
import io.circe.Decoder
val toDecoder: HAlgebra[QueryF, Decoder] = new HAlgebra[QueryF, Decoder] {
override def apply[A](fa: QueryF[Decoder, A]): Decoder[A] = fa match {
case QueryBoolF => Decoder.decodeBoolean
case QueryStringF => Decoder.decodeString
case q: QueryPathF[Decoder, A] =>
Decoder.instance { cursor =>
cursor.get(q.path)(q.next)
val nestedQuery = queryPath(
"oh",
queryPath(
"my",
queryString
)
)
// a trick to fold into String, this is interesting as it shows that
// generalized type constructor is super powerful; it can represent a
type HAlgebra[F[_[_], _], G[_]] = F[G, ?] ~> G
def hCata[F[_[_], _], G[_], I](alg: HAlgebra[F, G],hfix: HFix[F, I])(implicit F: HFunctor[F]): G[I] = {
val inner = hfix.unfix
val nt = F.hmap(
new (HFix[F, ?] ~> G) {
def apply[A](fa: HFix[F, A]): G[A] = hCata(alg, fa)
}
)(inner)
alg(nt)
}
implicit val queryHFunctor: HFunctor[QueryF] = new HFunctor[QueryF] {
def hmap[I[_], J[_]](nt: I ~> J): QueryF[I, ?] ~> QueryF[J, ?] = {
new (QueryF[I, ?] ~> QueryF[J, ?]) {
def apply[A](a: QueryF[I, A]): QueryF[J, A] = {
a match {
case QueryStringF => QueryStringF
case QueryBoolF => QueryBoolF
case query: QueryPathF[I, A] => QueryPathF(query.path, nt(query.next))
}
}
import $ivy.`org.typelevel::cats-core:1.6.0`
import cats.~>
trait HFunctor[F[_[_], _]] {
def hmap[I[_], J[_]](nt: I ~> J): F[I, ?] ~> F[J, ?]
}
def queryString = HFix(QueryStringF: QueryF[HFix[Query,?], String])
def queryBool = HFix(QueryBoolF: Query[HFix[QueryF,?], Boolean])
def queryPath[A](p: String, next: HFix[QueryF, A]) = HFix(QueryPathF(p, HFix(next)))
queryPath(
"oh",
queryPath(
"my",
queryString
)