xacid: (Default)
2019-10-22 09:15 am
Entry tags:

Open union (Scala 2)

    trait in[A, B] {
      def inj(a: A): B
    }
    object in {
      implicit def inSelf[A]: (A in A) = (a: A) => a
      implicit def inHead[A, B]: (A in (A Either B)) = (a: A) => Left(a)
      implicit def inRight[A, B, C](implicit r: (A in C)): (A in (B Either C)) =
        (a: A) => Right(r.inj(a))
      implicit def inLeft[A, B, C](implicit r: (A in B)): (A in (B Either C)) =
        (a: A) => Left(r.inj(a))
    }
Read more... )
xacid: (Default)
2019-08-27 12:05 pm
Entry tags:

The Science of Functional Programming

https://github.com/winitzki/sofp/blob/master/sofp-src/sofp.pdf

The Science of Functional Programming
A Tutorial, with Examples in Scala

by Sergei Winitzki, Ph.D.
draft version, August 16, 2019
xacid: (Default)
2019-07-01 10:42 am
Entry tags:

Effekt : Extensible Effect Handlers in Scala

http://ps.informatik.uni-tuebingen.de/publications/brachthaeuser19effekt.pdf

https://github.com/b-studios/scala-effekt

Effect handlers are a promising way to structure effectful programs in a modular way. We present the Scala library Effekt, which is centered around capability passing and implemented in terms of a monad for multi-prompt delimited continuations. Effekt is the first practical implementation of effect handlers that supports effect safety, effect polymorphism, effect parametricity, and effect encapsulation which means that all effects are handled and effects cannot be accidentally handled by the wrong handler. Other existing languages and libraries break effect encapsulation by leaking implementation details in the effect type unless the user manually adds lifting annotations. We describe a novel way of achieving effect-safety using intersection types and path dependent types. We represent effect rows as the contravariant intersection of effect types, where an individual effect is represented by the singleton type of its capability. Handlers remove components of the intersection type. By reusing the existing type system we get subtyping and polymorphism of effects for free. The effect system not only guarantees safety, but also guarantees modular reasoning about higher-order effectful programs.
xacid: (Default)
2019-06-02 01:57 pm
Entry tags:

Лёд тронулся

по мотивам https://xacid.dreamwidth.org/70479.html где я недоумевал по поводу отсутсвия в дотти синт-сахара для полиморфных лямбд и вобще функций первого класса - кажется до них таки это доперло

https://github.com/lampepfl/dotty/pull/4672

теперь в дотти будут (уже замержили в мастер) такие полиморфные лямбды

// Polymorphic idenity
val pid = [T] => (t: T) => t

// Function with poly function argument
val mf = (f: [U] => U => U, t: Int) => f(t)
val mf0 = mf(pid, 23)
xacid: (Default)
2017-08-06 10:23 pm
Entry tags:

Dotty / Scala 3.0 forAll

Поиграл немного с недавней 0.2.0-RC1 dotty и кроме того что там еще всё сыро (это конечно ожидаемо) обнаружил еще один для меня лично достаточно неприятный факт который можно проиллюстрировать вот этой ссылкой

https://github.com/lampepfl/dotty/issues/2500

Проблема заключается в том что несмотря на то что в дотти уже реализованно частичное применение типов и даже на первый взгляд вроде бы нормальные лямбды на уровне типов (в дотти это одно и то же, кстати Одерский на эту тему написал целый пейпер) , практическое применение этой привлекательной и потенциально полезной возможности остается по большей части не ясным по причине все еще отсутствия в дотти нормальных же полиморфных значений с квантификатором forAll, а при попытке какого либо использования частично примененного типа или его лямбды компилятор начинает либо требовать полного применения типа либо просто жалуется что не найден параметр типа. Выше ссылка на предложение таки добавить логичное forAll чтобы это начало нормально работать однако не заметно чтобы это предложение нашло поддержку со стороны Одерского и судя по всему нет уверенности что таки это както решится (хотя конечно хочется в это верить). А жаль :(

С другой стороны конечно я возможно чего нибудь пока не понимаю в этом вопросе :)
xacid: (Default)
2017-05-21 05:41 pm
Entry tags:

Flare: Native Compilation for Heterogeneous Workloads in Apache Spark

https://arxiv.org/pdf/1703.08219.pdf

We present Flare: a new back-end for Spark that brings performance closer to the best SQL engines, without giving up the added expressiveness of Spark. We demonstrate order of magnitude speedups both for relational workloads such as TPC-H, as well as for a range of machine learning kernels that combine relational and iterative functional processing.
Flare achieves these results through (1) compilation to native code, (2) replacing parts of the Spark runtime system, and (3) extending the scope of optimization and code generation to large classes of UDFs.
xacid: (Default)
2017-03-15 10:17 am
Entry tags:

Scala Native 0.1

http://www.scala-native.org/en/latest/

самое приятное - работает!
xacid: (Default)
2017-01-20 12:41 am
Entry tags:

Simple

import org.parboiled2._

object Simple extends App {

  trait LambdaCalculus[T] {
    def ref(n: String): T
    def lam(n: String, t: T): T
    def app(f: T, a: T): T
  }

  trait Expr[T] {
    def oper(a: T, f: String, b: T): T
    def parens(a: T): T
  }

  trait Literals[T] {
    def int(i: Int): T
  }

  trait Sym[T] extends LambdaCalculus[T]
    with Expr[T] with Literals[T]

  trait Ast {
    def apply[T: Sym]: T
  }

  trait SymAst extends Sym[Ast] {
    import Ast._

    def ref(n: String): Ast = Ref(n)
    def lam(n: String, t: Ast): Ast = Lam(n, t)
    def app(f: Ast, a: Ast): Ast = App(f, a)
    def oper(a: Ast, f: String, b: Ast): Ast = Oper(a, f, b)
    def parens(a: Ast): Ast = Parens(a)
    def int(i: Int): Ast = IntV(i)
  }
Read more... )

  val main = "(x -> y -> z -> y * ( x + y * z))"
  val answer = parser(main)

  println(answer.map(ShowSym(_)))
  println(answer.map(SymVM(_, 1, 2, 10)))

  println(parser(main + " 1 2 10").map(x =>
    ShowSym(x) + " = " + SymVM(x)))

}
xacid: (Default)
2016-12-13 12:48 am
Entry tags:

Tagless types

object Types extends App {

  trait Typed[F[_]] {
    def Bool: F[Boolean]
    def Int: F[Int]
    def Str: F[String]
    def ->[A, B](a: F[A], b: F[B]): F[A => B]
    def *[A, B](a: F[A], b: F[B]): F[(A, B)]
  }
object Typed ... )
xacid: (Default)
2016-12-10 11:24 pm
Entry tags:

Tagless calculator

import org.parboiled2._

object Tagless extends App {

  trait Sym[F[_]] {
    def lit[A]: (String, A) => F[A]
    def app[A, B]: F[A => B] => F[A] => F[B]
    def lam[A, B]: String =>
      (F[A] => F[B]) => F[A => B]
  }

  type RunSym[A] = A
  object RunSym extends Sym[RunSym] {
    def lit[A] = (_, a) => a
    def app[A, B] = f => a => f(a)
    def lam[A, B] = s => f => f
  }

  type ShowSym[A] = String
  object ShowSym extends Sym[ShowSym] {
    def lit[A] = (s, _) => s
    def app[A, B] = f => a => s"$f($a)"
    def lam[A, B] = s => f => s"($s => ${f(s)})"
  }

  trait FSym[A] { def apply[F[_] : Sym]: F[A] }
  object FSym {
    def sym[F[_] : Sym] = implicitly[Sym[F]]
    def lit[A](s: String, a: A) = new FSym[A] {
      def apply[F[_] : Sym]: F[A] = sym.lit(s, a)
    }
    def lit[A](a: A) = new FSym[A] {
      def apply[F[_] : Sym]: F[A] = sym.lit(a.toString, a)
    }
    def app[A, B](f: FSym[A => B], a: FSym[A]) = new FSym[B] {
      def apply[F[_] : Sym]: F[B] = sym.app(f[F])(a[F])
    }
  }

  def showRunSym[A](f: FSym[A]) =
    s"${f(ShowSym)} = ${f(RunSym)}"

  object CalcSym {
    def int(x: String) = FSym.lit(x.toInt)
    def calc(f: FSym[Int => Int => Int]) =
      (x: FSym[Int], y: FSym[Int]) =>
        FSym.app(FSym.app(f, x), y)
    val PLUS = calc(FSym.lit("+", (x: Int) => x + _))
    val MINUS = calc(FSym.lit("-", (x: Int) => x - _))
    val MUL = calc(FSym.lit("*", (x: Int) => x * _))
    val DIV = calc(FSym.lit("-", (x: Int) => x / _))
  }

  class CalcSym(val input: ParserInput) extends Parser {
    import CalcSym._
    def parser = rule(Expr ~ EOI)
    def Expr: Rule1[FSym[Int]] =
      rule(Term ~ (Plus | Minus).+)
    def Term = rule(Factor ~ (Mul | Div).+)
    def Factor = rule(Number | Parens)
    def Plus = rule('+' ~ Term ~> PLUS)
    def Minus = rule('-' ~ Term ~> MINUS)
    def Mul = rule('*' ~ Factor ~> MUL)
    def Div = rule('/' ~ Factor ~> DIV)
    def Parens = rule(sp ~ '(' ~ sp ~ Expr ~ sp ~ ')' ~ sp)
    def Number = rule(sp ~ capture(Digits) ~ sp ~> (int _))
    def Digits = rule(CharPredicate.Digit.+)
    def sp = rule(zeroOrMore(' '))
  }

  val main = "(10 * 2 + 1) * 2"

  val answer = new CalcSym(main).parser.run()

  answer map showRunSym map println

}

// *(+(*(10)(2))(1))(2) = 42

xacid: (Default)
2016-12-10 03:11 am
Entry tags:

Tagless free

import cats._
import cats.implicits._
import scala.concurrent._
import scala.concurrent.duration.Duration._
import ExecutionContext.Implicits.global

object Tagless extends App {

  trait Sym[F[_]] {
    def lit[A]: (String, A) => F[A]
    def app[A, B]: F[A => B] => F[A] => F[B]
    def lam[A, B]: String => (F[A] => F[B]) => F[A => B]
  }

  object Sym {
    def apply[F[_] : Sym] = implicitly[Sym[F]]
    def lit[F[_] : Sym, A](s: String, a: A) =
      Sym[F].lit(s, a)
    def lit[F[_] : Sym, A](a: A) =
      Sym[F].lit(a.toString, a)
    def app[F[_] : Sym, A, B](f: F[A => B])
                             (a: F[A]) = Sym[F].app(f)(a)
    def lam[F[_] : Sym, A, B](s: String)
                             (f: (F[A] => F[B])) = Sym[F].lam(s)(f)
  }

  trait FreeSym[A] {
    def run: A
    def lift[F[_] : Applicative]: F[A]
  }

  object FreeSym extends Sym[FreeSym] {

    case class Lit[A](s: String, a: A) extends FreeSym[A] {
      override def run: A = a
      override def lift[F[_] : Applicative]: F[A] =
        Applicative[F].pure(a)
    }

    case class App[A, B](f: FreeSym[A => B],
                         a: FreeSym[A]) extends FreeSym[B] {
      override def run: B = f.run(a.run)
      override def lift[F[_] : Applicative]: F[B] =
        Applicative[F].ap(f.lift[F])(a.lift[F])
    }

    case class Lam[A, B](s: String,
                         f: FreeSym[A] => FreeSym[B])
      extends FreeSym[A => B] {
      override def run: (A) => B = a => f(Lit(s, a)).run
      override def lift[F[_] : Applicative]: F[(A) => B] =
        Applicative[F].pure(run)
    }

    override def lit[A] = Lit[A] _
    override def app[A, B] = f => a => App(f, a)
    override def lam[A, B] = s => f => Lam(s, f)
  }

  import Sym._

  def PLUS[F[_] : Sym] = lit("+",
    (x: Int) => (y: Int) => x + y)

  def main[F[_] : Sym] = lam("x")((x: F[Int]) =>
    app(app(PLUS)(x))(x))

  def answer[F[_] : Sym] = app(main)(lit(21))

  println(Await.result(answer(FreeSym).lift[Future], Inf))

}
xacid: (Default)
2016-12-09 05:56 pm
Entry tags:

More tagless

object Tagless extends App {

  trait Sym[F[_]] {
    def lit[A]: (String, A) => F[A]
    def app[A, B]: F[A => B] => F[A] => F[B]
    def lam[A, B]: String => (F[A] => F[B]) => F[A => B]
  }

  object Sym {
    def apply[F[_] : Sym] = implicitly[Sym[F]]
    def lit[F[_] : Sym, A](s: String, a: A) = 
       Sym[F].lit(s, a)
    def lit[F[_] : Sym, A](a: A) = 
       Sym[F].lit(a.toString, a)
    def app[F[_] : Sym, A, B](f: F[A => B])
       (a: F[A]) = Sym[F].app(f)(a)
    def lam[F[_] : Sym, A, B](s: String)
       (f: (F[A] => F[B])) = Sym[F].lam(s)(f)
  }

  type RunSym[A] = A
  object RunSym extends Sym[RunSym] {
    override def lit[A]: (String, A) => RunSym[A] =
      (_, a) => a
    override def app[A, B]: (RunSym[(A) => B]) => 
      (RunSym[A]) => RunSym[B] = f => a => f(a)
    override def lam[A, B]: String => 
      ((RunSym[A]) => RunSym[B]) => RunSym[(A) => B] =
       s => f => f
  }

  type ShowSym[A] = String
  object ShowSym extends Sym[ShowSym] {
    override def lit[A]: (String, A) => ShowSym[A] = 
      (s, _) => s
    override def app[A, B]: (ShowSym[(A) => B]) => 
      (ShowSym[A]) => ShowSym[B] = f => a => s"$f($a)"
    override def lam[A, B]: String => 
      ((ShowSym[A]) => ShowSym[B]) => ShowSym[(A) => B] =
       s => f => s"($s => ${f(s)})"
  }

  import Sym._

  def PLUS[F[_] : Sym] = lit("+",
    (x: Int) => (y: Int) => x + y)

  def main[F[_] : Sym] = lam("x")((x: F[Int]) =>
    app(app(PLUS)(x))(x))

  def answer[F[_] : Sym] = app(main)(lit(21))

  println(s"${answer(ShowSym)} = ${answer(RunSym)}")

}

// (x => +(x)(x))(21) = 42
xacid: (Default)
2016-12-09 12:17 am
Entry tags:

Finally tagless

object Tagless extends App {

  trait Sym[F[_]] {
    def lit[A](a: A): F[A]
    def app[A, B](f: F[A => B])(a: F[A]): F[B]
    def lam[A, B](f: F[A] => F[B]): F[A => B]
  }

  object Sym {
    def apply[F[_] : Sym] = implicitly[Sym[F]]
    def lit[F[_] : Sym, A](a: A): F[A] = Sym[F].lit(a)
    def app[F[_] : Sym, A, B](f: F[A => B])(a: F[A]): F[B] = 
      Sym[F].app(f)(a)
    def lam[F[_] : Sym, A, B](f: F[A] => F[B]): F[A => B] = 
      Sym[F].lam(f)
  }

  type RunSym[A] = A
  object RunSym {
    implicit object runSym extends Sym[RunSym] {
      override def lit[A](a: A): RunSym[A] = a
      override def app[A, B](f: RunSym[(A) => B])
         (a: RunSym[A]): RunSym[B] = f(a)
      override def lam[A, B](f: (RunSym[A]) => 
          RunSym[B]): RunSym[(A) => B] = f
    }
  }

  import Sym._

  def PLUS(x: Int)(y: Int) = x + y

  def answer[F[_] : Sym] = lam((x: F[Int]) =>
    app(app(lit(PLUS _))(x))(x))

  import RunSym._

  println(answer[RunSym].apply(21))

}
xacid: (Default)
2016-11-26 11:11 pm
Entry tags:

Applicative functor is Lambda Calculus

  import cats._
  import cats.implicits._
  import scala.concurrent._
  import scala.concurrent.duration.Duration._
  import scala.concurrent.ExecutionContext.Implicits.global

  trait Lam[F[_]] {
    def lit[A](a: A): F[A]
    def op[A, B](f: A => B): F[A => B]
    def app[A, B](f: F[A => B])(a: F[A]): F[B]
  }

  object Lam {
    def apply[F[_] : Lam] = implicitly[Lam[F]]
    def lit[F[_] : Lam, A](a: A): F[A] = Lam[F].lit(a)
    def op[F[_] : Lam, A, B](f: A => B): F[A => B] =
      Lam[F].op(f)

    def app[F[_] : Lam, A, B](f: F[A => B])
                             (a: F[A]): F[B] =
      Lam[F].app(f)(a)

    def lam[F[_] : Lam, A, B](f: F[A] => F[B]) = f
  }

  implicit def applam[F[_] : Applicative]: Lam[F] =
    new Lam[F] {
      def lit[A](a: A): F[A] =
        Applicative[F].pure(a)

      def op[A, B](f: A => B): F[(A) => B] =
        Applicative[F].pure(f)

      def app[A, B](f: F[A => B])(a: F[A]): F[B] =
        Applicative[F].ap(f)(a)
    }

  val PLUS = ((_: Int) + (_: Int)).curried

  import Lam._

  def answer[F[_] : Lam] = lam((x: F[Int]) =>
    app(app(op(PLUS))(x))(x))

  def main[F[_] : Lam : Functor] =
    answer[F].andThen(_.map(println))

  main[Id].apply(21)

  Await.ready(main[Future].apply(Future(21)), Inf)
xacid: (Default)
2016-11-23 02:34 am
Entry tags:

SK lambda


import cats._
import cats.data._
import cats.implicits._

import scala.concurrent._
import scala.concurrent.duration.Duration._
import ExecutionContext.Implicits.global

object Sk extends App {
  val PLUS = ((_: Int) + (_: Int)).curried

  trait Lam_[->>[_, _]] {
    def app[E, A, B]: E ->> (A => B) => E ->> A => E ->> B

    def fun[A, B]: (A => B) => A ->> (A => B)

    def lam[A, B]: (A ->> A => A ->> B) => A ->> B
  }

  trait Lam[F[_]] extends Lam_[Kleisli[F, ?, ?]]

  implicit def lama[F[_] : Applicative]: Lam[F] =
    new Lam[F] {
      def AP[E] = Applicative[Kleisli[F, E, ?]]

      def app[E, A, B] = AP[E].ap[A, B]

      def fun[A, B] = AP[A].pure[A => B]

      def lam[A, B] = _ (Kleisli.ask[F, A])
    }

  object Lam {
    def apply[F[_] : Lam] = implicitly[Lam[F]]

    def app[F[_] : Lam, E, A, B](f: Kleisli[F, E, (A => B)])
                                (a: Kleisli[F, E, A]) =
      Lam[F].app(f)(a)

    def fun[F[_] : Lam, A, B](f: A => B) = Lam[F].fun(f)

    def lam[F[_] : Lam, A, B](f: Kleisli[F, A, A] =>
      Kleisli[F, A, B]) = Lam[F].lam(f)
  }

  import Lam._

  def answer[F[_] : Lam]: Kleisli[F, Int, Int] =
    lam(x => app(app(fun(PLUS))(x))(x))

  def main[F[_] : Lam : Functor] = answer[F].map(println)

  answer[Id].apply(21)

  Await.ready(main[Future].apply(21), Inf)

}

xacid: (Default)
2016-11-22 02:59 am
Entry tags:

how to coap?

  import cats._

  trait Sym[F[_]] {
    def lit[A]: A => F[A] // pure

    def app[A, B]: F[A => B] => F[A] => F[B] // ap

    def lam[A, B]: (F[A] => F[B]) => F[A => B] // coap?
  }

  implicit def symm[F[_] : Bimonad]: Sym[F] =
    new Sym[F] {

      val M = Bimonad[F]

      def lit[A] = M.pure[A]

      def app[A, B] = M.ap[A, B]

      def lam[A, B] = f =>
        M.pure[A => B](a =>
          M.extract(f(M.pure(a))))
    }

  val PLUS = ((_: Int) + (_: Int)).curried

  def answer[F[_] : Sym]: F[Int => Int] = {
    val sym = implicitly[Sym[F]]
    import sym._
    lam(x => app(app(lit(PLUS))(x))(x))
  }