From Tagless-Final to Typed-Final: Program Transformations in the Final Style

0fd215d10cc3a6517eb482d1cd6bea8d?s=47 dcube
September 16, 2019

From Tagless-Final to Typed-Final: Program Transformations in the Final Style

0fd215d10cc3a6517eb482d1cd6bea8d?s=128

dcube

September 16, 2019
Tweet

Transcript

  1. From Tagless-Final to Typed-Final Program Transformations in the Final Style

    Kenichi Suzuki BizReach, Inc. ken@succ0.org
  2. ໨࣍ • ࣗݾ঺հ • tagless-finalͱ͸ • typed-final styleͰϓϩάϥϜม׵

  3. ࣗݾ঺հ • ླ໦ ݈Ұ (Kenichi Suzuki) • ken@succ0.org • github.com/knih

    • QUEΛ (http://logic.cs.tsukuba.ac.jp/~ken/quel/) • ϓϩάϥϜݴޠ࿦ɺΫΤϦɺFunctional DDD • BizReach • yamory (https://yamory.io)
  4. The Death of Tagless Final

  5. Pure repository trait UserRepository[F[_]] { def findOneById(userId: UserId): F[Option[User]] }

    class UserService[F[_]](userRepository: UserRepository[F]) (implicit ME: MonadError[F, Error]) { def getName(userId: String) = { val userOptF: F[Option[User]] = userRepository.findOneById(userId) Monad[F].map(userOptF) { userOpt => for { user <- userOpt } yield user.name } } }
  6. Pure repository object UserRepositoryOnJdbc extends UserRepository[IO] { override def findOneById(userId:

    UserId): IO[Option[User]] = ??? } object UserController extends ApplicationController { implicit val userRepository: UserRepository[IO] = UserRepositoryOnJdbc val service = new UserService[IO] ... }
  7. What is Tagless Final?

  8. tagless-finalͱ͸ • ܕ҆શͳຒࠐΈDSLΛߏங͢Δख๏ • ܕ෇͚͕ϝλݴޠ (ϗετݴޠ) ͷͦΕʹؼண͢Δ • ܕݕࠪΞϧΰϦζϜΛ࣮૷͠ͳͯ͘Α͍ •

    HOAS (ߴ֊ந৅ߏจ) ͕࢖͑Δ • ϝλݴޠʹΑͬͯείʔϓ҆શੑ͕୲อ͞ΕΔ • ݴޠίϯϙʔωϯτͷ߹੒Λαϙʔτ • ύʔαΛ࡞Βͳͯ͘Α͍ • ϗετݴޠͷΤίγεςϜ͕࢖͑Δ [J. Carette, O. Kiselyov and C.-c. Shan. (2009)] [1]
  9. ର৅ݴޠͱϝλݴޠ • ର৅ݴޠ (object language) • දݱ͍ͨ͠ݴޠɺDSL • ϝλݴޠ (meta

    language) • Scala, OCaml, Haskell౳ͷຒࠐΈઌϗετݴޠ
  10. Symantics Symantics ΠϯλϑΣʔε Symantics ΠϯλϓϦλ ߏจ(Syntax) ͱ ܕنଇ Symantics ΠϯλϓϦλ

    Symantics ΠϯλϓϦλ ҙຯ࿦(Semantics)
  11. ର৅ݴޠΛઃܭ͢Δ n is an integer n : Z <latexit sha1_base64="aqTjJRpsuHiTjvolHIL1iUnYxkc=">AAAClXichVHLShxBFD22STSThxNdKLhpHAxZDXdMwCAIohLc+RyVODJUtzVjYXd1010zqE3/QD4gWWSlEIL4C9mFiD+QhZ8QsjSQTRa53dMQEklym646de49t05VOaGnYkN01Wf137p9Z2Dwbune/QcPh8qPhjfjoBO5su4GXhBtOyKWntKybpTx5HYYSeE7ntxyDhay/FZXRrEK9IY5CuWuL9patZQrDFPNMjX2WpFwE203jDw0ia1iW2hbaSPbMkpTTszYDV+YfcdJXqZpqVmuUJXysG+CWgEqKGIlKL9HA3sI4KIDHxIahrEHgZi/HdRACJnbRcJcxEjleYkUJdZ2uEpyhWD2gMc2r3YKVvM66xnnapd38fiPWGljkj7TGV3TJZ3TF/rx115J3iPzcsSz09PKsDn0amz9+39VPs8G+79U//Rs0MLz3Kti72HOZKdwe/ru8Zvr9Zm1yeQxndJX9n9CV/SRT6C739x3q3LtLbIHqP153TfB5lS19rQ6tfqsMjdfPMUgxjGBJ3zf05jDElZQ531f4wM+4cIatWatRetFr9TqKzQj+C2s5Z/yAZyG</latexit>

    e1 : Z e2 : Z e1 + e2 : Z <latexit sha1_base64="EQqF3aFNjRqdenwIiwdw5Lz7pWE=">AAACqHichVHLSiNBFD326IwTdczoRnDTGJRBIVTHgZGsRDcu4yPGR6Sp7lRiY7/srgScJj/gD7hw5YCI+Blu3LkamHyCuHRgNi683WlQR9RbVNWtU+fcOlVl+LYVSsY6PcqH3r6Pn/o/ZwYGh74MZ7+OrIdeMzBF2fRsL9gweChsyxVlaUlbbPiB4I5hi4qxtxjvV1oiCC3PXZMHvthxeMO16pbJJUF6drFaqwfcjISuqUW16nC5axjRVlut7u83eU0VeqH4iLZj3kyMPaG29WyO5VkS6stES5Mc0ih52TNUUYMHE004EHAhKbfBEVLbhgYGn7AdRIQFlFnJvkAbGdI2iSWIwQndo7FBq+0UdWkd1wwTtUmn2NQDUqqYZL/ZObtjV+yC3bD7V2tFSY3YywHNRlcrfH34cGz137sqh2aJ3UfVm54l6phLvFrk3U+Q+BZmV9/6eXS3WlyZjKbYL3ZL/k9Yh13SDdzWX/N0WawcI0MfoP3/3C+T9UJem80Xlr/n5hfSr+jHOCbwjd77B+axhBLKdO45rvEHHWVaKSkVZbNLVXpSzSiehWI8AA4Yo7E=</latexit> e ::= n | e + e <latexit sha1_base64="BnNsj3R8j7NTot2dpjzNjA9F+qc=">AAACinichVFNSxtBGH5ctU1XrVEvBS9DQ6SghEksqAkF0R48JmpUcCXsrqMO2S92N4EY/AP2B/TQk4KI9ORVj176Bzz4E8SjghcPvrtZECvqu+zM8z7zPu88M2N4lgxCzq+6lO6e3g8fU5/Uvv6Bz4PpoeGVwG34pqiaruX6a4YeCEs6ohrK0BJrni9027DEqlGfj9ZXm8IPpOsshy1PbNj6tiO3pKmHRNXSWcGKxR9sTCs5TNNUxphmy80o1yYEG48GVVVr6QzP8TjYS5BPQAZJlN30MTRswoWJBmwIOAgJW9AR0LeOPDg84jbQJs4nJON1gT2opG1QlaAKndg6jduUrSesQ3nUM4jVJu1i0e+TkiHLL/kJv+X/+F9+zR9e7dWOe0ReWjQbHa3waoP7X5bu31XZNIfYeVK96TnEFqZjr5K8ezETncLs6Ju7v2+XiovZ9hg/5Dfk/4Bf8Qs6gdO8M48qYvEPogfI/3/dL8FKIZefzBUq3zOzc8lTpDCKr/hG9z2FWSygjCrt+wunOMO50q8UlBml1ClVuhLNCJ6F8vMRh1OStw==</latexit> ߏจ (syntax) ܕ෇͚نଇ (typing rules) දݱ͍ͨ͠ର৅ݴޠ Symantics trait AddSym { type Repr[T] def int(n: Int): Repr[Int] def add(t1: Repr[Int], t2: Repr[Int]): Repr[Int] }
  12. trait AddSym { type Repr[T] def int(n: Int): Repr[Int] def

    add(t1: Repr[Int], t2: Repr[Int]): Repr[Int] } ର৅ݴޠΛઃܭ͢Δ n is an integer n : Z <latexit sha1_base64="aqTjJRpsuHiTjvolHIL1iUnYxkc=">AAAClXichVHLShxBFD22STSThxNdKLhpHAxZDXdMwCAIohLc+RyVODJUtzVjYXd1010zqE3/QD4gWWSlEIL4C9mFiD+QhZ8QsjSQTRa53dMQEklym646de49t05VOaGnYkN01Wf137p9Z2Dwbune/QcPh8qPhjfjoBO5su4GXhBtOyKWntKybpTx5HYYSeE7ntxyDhay/FZXRrEK9IY5CuWuL9patZQrDFPNMjX2WpFwE203jDw0ia1iW2hbaSPbMkpTTszYDV+YfcdJXqZpqVmuUJXysG+CWgEqKGIlKL9HA3sI4KIDHxIahrEHgZi/HdRACJnbRcJcxEjleYkUJdZ2uEpyhWD2gMc2r3YKVvM66xnnapd38fiPWGljkj7TGV3TJZ3TF/rx115J3iPzcsSz09PKsDn0amz9+39VPs8G+79U//Rs0MLz3Kti72HOZKdwe/ru8Zvr9Zm1yeQxndJX9n9CV/SRT6C739x3q3LtLbIHqP153TfB5lS19rQ6tfqsMjdfPMUgxjGBJ3zf05jDElZQ531f4wM+4cIatWatRetFr9TqKzQj+C2s5Z/yAZyG</latexit> e1 : Z e2 : Z e1 + e2 : Z <latexit sha1_base64="EQqF3aFNjRqdenwIiwdw5Lz7pWE=">AAACqHichVHLSiNBFD326IwTdczoRnDTGJRBIVTHgZGsRDcu4yPGR6Sp7lRiY7/srgScJj/gD7hw5YCI+Blu3LkamHyCuHRgNi683WlQR9RbVNWtU+fcOlVl+LYVSsY6PcqH3r6Pn/o/ZwYGh74MZ7+OrIdeMzBF2fRsL9gweChsyxVlaUlbbPiB4I5hi4qxtxjvV1oiCC3PXZMHvthxeMO16pbJJUF6drFaqwfcjISuqUW16nC5axjRVlut7u83eU0VeqH4iLZj3kyMPaG29WyO5VkS6stES5Mc0ih52TNUUYMHE004EHAhKbfBEVLbhgYGn7AdRIQFlFnJvkAbGdI2iSWIwQndo7FBq+0UdWkd1wwTtUmn2NQDUqqYZL/ZObtjV+yC3bD7V2tFSY3YywHNRlcrfH34cGz137sqh2aJ3UfVm54l6phLvFrk3U+Q+BZmV9/6eXS3WlyZjKbYL3ZL/k9Yh13SDdzWX/N0WawcI0MfoP3/3C+T9UJem80Xlr/n5hfSr+jHOCbwjd77B+axhBLKdO45rvEHHWVaKSkVZbNLVXpSzSiehWI8AA4Yo7E=</latexit> e ::= n | e + e <latexit sha1_base64="BnNsj3R8j7NTot2dpjzNjA9F+qc=">AAACinichVFNSxtBGH5ctU1XrVEvBS9DQ6SghEksqAkF0R48JmpUcCXsrqMO2S92N4EY/AP2B/TQk4KI9ORVj176Bzz4E8SjghcPvrtZECvqu+zM8z7zPu88M2N4lgxCzq+6lO6e3g8fU5/Uvv6Bz4PpoeGVwG34pqiaruX6a4YeCEs6ohrK0BJrni9027DEqlGfj9ZXm8IPpOsshy1PbNj6tiO3pKmHRNXSWcGKxR9sTCs5TNNUxphmy80o1yYEG48GVVVr6QzP8TjYS5BPQAZJlN30MTRswoWJBmwIOAgJW9AR0LeOPDg84jbQJs4nJON1gT2opG1QlaAKndg6jduUrSesQ3nUM4jVJu1i0e+TkiHLL/kJv+X/+F9+zR9e7dWOe0ReWjQbHa3waoP7X5bu31XZNIfYeVK96TnEFqZjr5K8ezETncLs6Ju7v2+XiovZ9hg/5Dfk/4Bf8Qs6gdO8M48qYvEPogfI/3/dL8FKIZefzBUq3zOzc8lTpDCKr/hG9z2FWSygjCrt+wunOMO50q8UlBml1ClVuhLNCJ6F8vMRh1OStw==</latexit> ߏจ (syntax) ܕ෇͚نଇ (typing rules) දݱ͍ͨ͠ର৅ݴޠ Symantics
  13. trait AddSym { type Repr[T] def int(n: Int): Repr[Int] def

    add(t1: Repr[Int], t2: Repr[Int]): Repr[Int] } ର৅ݴޠΛઃܭ͢Δ n is an integer n : Z <latexit sha1_base64="aqTjJRpsuHiTjvolHIL1iUnYxkc=">AAAClXichVHLShxBFD22STSThxNdKLhpHAxZDXdMwCAIohLc+RyVODJUtzVjYXd1010zqE3/QD4gWWSlEIL4C9mFiD+QhZ8QsjSQTRa53dMQEklym646de49t05VOaGnYkN01Wf137p9Z2Dwbune/QcPh8qPhjfjoBO5su4GXhBtOyKWntKybpTx5HYYSeE7ntxyDhay/FZXRrEK9IY5CuWuL9patZQrDFPNMjX2WpFwE203jDw0ia1iW2hbaSPbMkpTTszYDV+YfcdJXqZpqVmuUJXysG+CWgEqKGIlKL9HA3sI4KIDHxIahrEHgZi/HdRACJnbRcJcxEjleYkUJdZ2uEpyhWD2gMc2r3YKVvM66xnnapd38fiPWGljkj7TGV3TJZ3TF/rx115J3iPzcsSz09PKsDn0amz9+39VPs8G+79U//Rs0MLz3Kti72HOZKdwe/ru8Zvr9Zm1yeQxndJX9n9CV/SRT6C739x3q3LtLbIHqP153TfB5lS19rQ6tfqsMjdfPMUgxjGBJ3zf05jDElZQ531f4wM+4cIatWatRetFr9TqKzQj+C2s5Z/yAZyG</latexit> e1 : Z e2 : Z e1 + e2 : Z <latexit sha1_base64="EQqF3aFNjRqdenwIiwdw5Lz7pWE=">AAACqHichVHLSiNBFD326IwTdczoRnDTGJRBIVTHgZGsRDcu4yPGR6Sp7lRiY7/srgScJj/gD7hw5YCI+Blu3LkamHyCuHRgNi683WlQR9RbVNWtU+fcOlVl+LYVSsY6PcqH3r6Pn/o/ZwYGh74MZ7+OrIdeMzBF2fRsL9gweChsyxVlaUlbbPiB4I5hi4qxtxjvV1oiCC3PXZMHvthxeMO16pbJJUF6drFaqwfcjISuqUW16nC5axjRVlut7u83eU0VeqH4iLZj3kyMPaG29WyO5VkS6stES5Mc0ih52TNUUYMHE004EHAhKbfBEVLbhgYGn7AdRIQFlFnJvkAbGdI2iSWIwQndo7FBq+0UdWkd1wwTtUmn2NQDUqqYZL/ZObtjV+yC3bD7V2tFSY3YywHNRlcrfH34cGz137sqh2aJ3UfVm54l6phLvFrk3U+Q+BZmV9/6eXS3WlyZjKbYL3ZL/k9Yh13SDdzWX/N0WawcI0MfoP3/3C+T9UJem80Xlr/n5hfSr+jHOCbwjd77B+axhBLKdO45rvEHHWVaKSkVZbNLVXpSzSiehWI8AA4Yo7E=</latexit> e ::= n | e + e <latexit sha1_base64="BnNsj3R8j7NTot2dpjzNjA9F+qc=">AAACinichVFNSxtBGH5ctU1XrVEvBS9DQ6SghEksqAkF0R48JmpUcCXsrqMO2S92N4EY/AP2B/TQk4KI9ORVj176Bzz4E8SjghcPvrtZECvqu+zM8z7zPu88M2N4lgxCzq+6lO6e3g8fU5/Uvv6Bz4PpoeGVwG34pqiaruX6a4YeCEs6ohrK0BJrni9027DEqlGfj9ZXm8IPpOsshy1PbNj6tiO3pKmHRNXSWcGKxR9sTCs5TNNUxphmy80o1yYEG48GVVVr6QzP8TjYS5BPQAZJlN30MTRswoWJBmwIOAgJW9AR0LeOPDg84jbQJs4nJON1gT2opG1QlaAKndg6jduUrSesQ3nUM4jVJu1i0e+TkiHLL/kJv+X/+F9+zR9e7dWOe0ReWjQbHa3waoP7X5bu31XZNIfYeVK96TnEFqZjr5K8ezETncLs6Ju7v2+XiovZ9hg/5Dfk/4Bf8Qs6gdO8M48qYvEPogfI/3/dL8FKIZefzBUq3zOzc8lTpDCKr/hG9z2FWSygjCrt+wunOMO50q8UlBml1ClVuhLNCJ6F8vMRh1OStw==</latexit> ߏจ (syntax) ܕ෇͚نଇ (typing rules) දݱ͍ͨ͠ର৅ݴޠ Symantics Repr
  14. Symantics • syntaxͱtyping rulesΛؔ਺ͷγάχνϟͰද͢ • දݱܕ (representation type) Ͱܕ෇͚نଇΛ ද͢

    • ߴ֊ΧΠϯυΛ࢖͏ • polymorphic lifting ͸࢖Θͳ͍ • semantics Λؔ਺ͷ࣮૷Ͱද͢
  15. ϢʔβϓϩάϥϜ trait AddSym { type Repr[T] def int(n: Int): Repr[Int]

    def add(t1: Repr[Int], t2: Repr[Int]): Repr[Int] } class Program[S <: AddSym](val sym: S) { import sym._ val ex1 = add(int(1), int(0)) } ΠϯλϓϦλʢ࣮૷ʣʹ ґଘ͠ͳ͍Ϣʔβϓϩά ϥϜ͕هड़Ͱ͖Δ
  16. ΠϯλϓϦλ final case class R[A](unR: A) // type Id[A] =

    A object interp extends AddSym { type Repr[T] = R[T] def int(n: Int): R[Int] = R(n) def add(t1: R[Int], t2: R[Int]): R[Int] = R(t1.unR + t2.unR) } def eval[A](e: R[A]): A = e.unR trait AddSym { type Repr[T] def int(n: Int): Repr[Int] def add(t1: Repr[Int], t2: Repr[Int]): Repr[Int] } ܕ͕อଘ͞ΕΔ ධՁؔ਺
  17. ಈ͔͢ object test { val evaluator = Run.interp val p1

    = new Program(evaluator) def main(args: Array[String]) = { println("---------------------------------") println(evaluator.eval(p1.ex1)) // => 1 }
  18. HOASͰλந৅Λѻ͏ • HOAS (Higher-Order Abstract Syntax; ߴ֊ந৅ߏจ) • ม਺ଋറΛϗετݴޠͷλͰදݱ͢ΔςΫχοΫ •

    ม਺Λਖ਼֬ʹѻ͏ͷ͸ׂͱ໘౗ • ม਺໊͕ඃΒͳ͍Α͏ʹ͢Δ • de Bruijn ΠϯσοΫεΛ࢖͏৔߹Ͱ΋ɺ୅ೖૢ࡞࣌ͷΠ ϯσοΫεͷγϑτܭࢉ͸ඞཁ • capture-avoiding substitution [Miller and Nadathur (1987); Pfenning and Elliott. (1988)][2,3]
  19. • ม਺ଋറΛϗετݴޠʹ·͔ͤΔ HOASͰλந৅Λѻ͏ trait LamSym {
 type Repr[T] def lam[A,

    B](f: Repr[A] => Repr[B]): Repr[A => B] def app[A, B](e1: Repr[A => B], e2: Repr[A]): Repr[B] } [x : ⌧1] . . . e : ⌧2 x.e : ⌧1 ! ⌧2 <latexit sha1_base64="UddLExytD4zksBVgqaiIIEMZk0U=">AAAC23ichVE7b9RAEB6bV3ACOaBBorE4B1Gd1gcS6KoIGso8uCTS7em09k2OVfa8lr22Eqyr6CLaKAUVSAghfgYNf4AiEn8AUQaJhoLxQyASBcbyzrffzDczuxvESqaGsSPLPnf+wsVLc5ed+YUrVxdb165vpDpLQuyHWulkKxApKhlh30ijcCtOUEwDhZvBzuMyvpljkkodPTV7MQ6nYhLJbRkKQ9SolfMAJzIqjAgyJZJZEc4cb7Db40ZkI3/ouZw7PB9rk5bIwzrQrXiPaypddi64opZj4e66HRd7bq0mp2vYnXkOx2j8u82o1WYdVpl7GvgNaENjK7r1DjiMQUMIGUwBIQJDWIGAlL4B+MAgJm4IBXEJIVnFEWbgkDajLKQMQewOrRPaDRo2on1ZM63UIXVR9CekdGGJfWbv2TH7xD6wr+znmbWKqkY5yx75oNZiPFrcv7n+47+qKXkDz/6o/jmzgW14WM0qafa4YspThLU+f354vN5bWyrusDfsG83/mh2xj3SCKP8evl3FtVfg0AP4J6/7NNjodvx7ne7q/fbyo+Yp5uAW3Ia7dN8PYBmewAr0qe8Xy7bmrQV7aL+w9+2XdaptNZob8JfZB78AP0qzGg==</latexit> e1 : ⌧1 ! ⌧2 e2 : ⌧1 e1 e2 : ⌧2 <latexit sha1_base64="DZcBi/QMqSJUFwC2VULSF/1G15s=">AAACqXichVFNSxtBGH5cW7WxamwvhV6WBosghNm0oKSXUHvwaLTRUFeW2ckkLm52193ZQAz5A/4BD55aKNL2Z3jx2IuH+A9Kjwq99NB3P6C0or7LzjzzvM/zzjszduA6kWJsNKaNP3g4MTn1qDD9eGZ2rjj/ZCvy41DIhvBdP2zaPJKu48mGcpQrm0Eoedd25ba9v5rkt3syjBzfe6/6gdzt8o7ntB3BFVFW8Z3ZaodcDKRl6FXdVDwmYCo/gxXdPDiIeUuXVqWaJYeJ1HyTELlmWLCKJVZmaeg3gZGDEvJY94unMNGCD4EYXUh4UIRdcET07cAAQ0DcLgbEhYScNC8xRIG8MakkKTix+zR2aLWTsx6tk5pR6ha0i0t/SE4dC+yCfWFX7Jx9Yz/Y71trDdIaSS99mu3MKwNr7ujZ5q97XV2aFfb+uu7sWaGNlbRXh3oPUiY5hcj8vcPjq83qxsLgJfvEflL/H9mIndEJvN61+FyXGydIHsD4/7pvgq1K2XhVrtRfl2pv86eYwnO8wCLd9zJqWMM6GrTvV3zHCJfaklbXmtqHTKqN5Z6n+Cc08QcZZKI2</latexit>
  20. • ม਺ଋറΛϗετݴޠʹ·͔ͤΔ HOASͰλந৅Λѻ͏ trait LamSym {
 type Repr[T] def lam[A,

    B](f: Repr[A] => Repr[B]): Repr[A => B] def app[A, B](e1: Repr[A => B], e2: Repr[A]): Repr[B] } [x : ⌧1] . . . e : ⌧2 x.e : ⌧1 ! ⌧2 <latexit sha1_base64="UddLExytD4zksBVgqaiIIEMZk0U=">AAAC23ichVE7b9RAEB6bV3ACOaBBorE4B1Gd1gcS6KoIGso8uCTS7em09k2OVfa8lr22Eqyr6CLaKAUVSAghfgYNf4AiEn8AUQaJhoLxQyASBcbyzrffzDczuxvESqaGsSPLPnf+wsVLc5ed+YUrVxdb165vpDpLQuyHWulkKxApKhlh30ijcCtOUEwDhZvBzuMyvpljkkodPTV7MQ6nYhLJbRkKQ9SolfMAJzIqjAgyJZJZEc4cb7Db40ZkI3/ouZw7PB9rk5bIwzrQrXiPaypddi64opZj4e66HRd7bq0mp2vYnXkOx2j8u82o1WYdVpl7GvgNaENjK7r1DjiMQUMIGUwBIQJDWIGAlL4B+MAgJm4IBXEJIVnFEWbgkDajLKQMQewOrRPaDRo2on1ZM63UIXVR9CekdGGJfWbv2TH7xD6wr+znmbWKqkY5yx75oNZiPFrcv7n+47+qKXkDz/6o/jmzgW14WM0qafa4YspThLU+f354vN5bWyrusDfsG83/mh2xj3SCKP8evl3FtVfg0AP4J6/7NNjodvx7ne7q/fbyo+Yp5uAW3Ia7dN8PYBmewAr0qe8Xy7bmrQV7aL+w9+2XdaptNZob8JfZB78AP0qzGg==</latexit> e1 : ⌧1 ! ⌧2 e2 : ⌧1 e1 e2 : ⌧2 <latexit sha1_base64="DZcBi/QMqSJUFwC2VULSF/1G15s=">AAACqXichVFNSxtBGH5cW7WxamwvhV6WBosghNm0oKSXUHvwaLTRUFeW2ckkLm52193ZQAz5A/4BD55aKNL2Z3jx2IuH+A9Kjwq99NB3P6C0or7LzjzzvM/zzjszduA6kWJsNKaNP3g4MTn1qDD9eGZ2rjj/ZCvy41DIhvBdP2zaPJKu48mGcpQrm0Eoedd25ba9v5rkt3syjBzfe6/6gdzt8o7ntB3BFVFW8Z3ZaodcDKRl6FXdVDwmYCo/gxXdPDiIeUuXVqWaJYeJ1HyTELlmWLCKJVZmaeg3gZGDEvJY94unMNGCD4EYXUh4UIRdcET07cAAQ0DcLgbEhYScNC8xRIG8MakkKTix+zR2aLWTsx6tk5pR6ha0i0t/SE4dC+yCfWFX7Jx9Yz/Y71trDdIaSS99mu3MKwNr7ujZ5q97XV2aFfb+uu7sWaGNlbRXh3oPUiY5hcj8vcPjq83qxsLgJfvEflL/H9mIndEJvN61+FyXGydIHsD4/7pvgq1K2XhVrtRfl2pv86eYwnO8wCLd9zJqWMM6GrTvV3zHCJfaklbXmtqHTKqN5Z6n+Cc08QcZZKI2</latexit>
  21. HOASͰλந৅Λѻ͏ • ΠϯλϓϦλ͸ܕ߹ΘͤήʔϜ def lam[A, B](f: R[A] => R[B]): R[A

    => B] = R((x: A) => f(R(x)).unR) def app[A, B](e1: R[A => B], e2: R[A]): R[B] = R(e1.unR(e2.unR))
  22. HOASͰλந৅Λѻ͏ • ΠϯλϓϦλ͸ܕ߹ΘͤήʔϜ def lam[A, B](f: R[A] => R[B]): R[A

    => B] = R((x: A) => f(R(x)).unR) def app[A, B](e1: R[A => B], e2: R[A]): R[B] = R(e1.unR(e2.unR))
  23. HOASͰλந৅Λѻ͏ • ΠϯλϓϦλ͸ܕ߹ΘͤήʔϜ def lam[A, B](f: R[A] => R[B]): R[A

    => B] = R((x: A) => f(R(x)).unR) def app[A, B](e1: R[A => B], e2: R[A]): R[B] = R(e1.unR(e2.unR))
  24. HOASͰλந৅Λѻ͏ • ΠϯλϓϦλ͸ܕ߹ΘͤήʔϜ def lam[A, B](f: R[A] => R[B]): R[A

    => B] = R((x: A) => f(R(x)).unR) def app[A, B](e1: R[A => B], e2: R[A]): R[B] = R(e1.unR(e2.unR))
  25. HOASͰλந৅Λѻ͏ • ΠϯλϓϦλ͸ܕ߹ΘͤήʔϜ def lam[A, B](f: R[A] => R[B]): R[A

    => B] = R((x: A) => f(R(x)).unR) def app[A, B](e1: R[A => B], e2: R[A]): R[B] = R(e1.unR(e2.unR))
  26. ݴޠίϯϙʔωϯτΛ߹੒ trait AddSym { type Repr[T] def int(n: Int): Repr[Int]

    def add(e1: Repr[Int], e2: Repr[Int]): Repr[Int] } trait SymLam { type Repr[T] def lam[A, B](f: Repr[A] => Repr[B]): Repr[A => B] def app[A, B](e1: Repr[A => B], e2: Repr[A]): Repr[B] } trait Sym extends AddSym with SymLam
  27. ݴޠίϯϙʔωϯτΛ߹੒ trait AddSym[Repr[_]] { def int(n: Int): Repr[Int] def add(e1:

    Repr[Int], e2: Repr[Int]): Repr[Int] } trait SymLam[Repr[_]] { def lam[A, B](f: Repr[A] => Repr[B]): Repr[A => B] def app[A, B](e1: Repr[A => B], e2: Repr[A]): Repr[B] } trait Sym[Repr[_]] extends AddSym[Repr] with SymLam[Repr]
  28. tagless-final ↓ typed-final

  29. ਁಁ͍ͯ͠ͳ͍ͷͰ΋͏Ұ౓

  30. typed-final

  31. ʢάάϥϏϦςΟΛߟ͍͑ͯͳ͔ͬͨʣ

  32. ϓϩάϥϜม׵ • ୯Ґݩ • n + 0 = n ...

    ӈ୯Ґݩ • 0 + m = m ... ࠨ୯Ґݩ • tagless-final͸ؔ਺ʹΑͬͯݴޠΛߏ੒͢Δ • ؔ਺Ͱߏ੒͞ΕͨϓϩάϥϜΛͲͷΑ͏ʹม׵͢Δ͔ val program: R[Int] = add(int(1), int(0))
  33. ϓϩάϥϜม׵ • tagless-final typed-final ͸1ͭͷΠϯλϑΣʔ ε(symantics)ʹରͯ͠ෳ਺ͷ࣮૷(ΠϯλϓϦ λ)Λ࣋ͭ͜ͱ͕Ͱ͖Δ

  34. ϓϩάϥϜม׵ Symantics ΠϯλϑΣʔε Symantics ΠϯλϓϦλ Symantics ΠϯλϓϦλ Symantics ΠϯλϓϦλ

  35. ϓϩάϥϜม׵ Symantics ΠϯλϑΣʔε Symantics ΠϯλϓϦλ Symantics ΠϯλϓϦλ

  36. ϓϩάϥϜม׵ Symantics ΠϯλϑΣʔε ධՁΠϯλϓϦλ ม׵ΠϯλϓϦλ

  37. ϓϩάϥϜม׵ • ධՁثΠϯλϓϦλ͸ͦͷ··࢖͍͍ͨ • ม׵ϩδοΫͱධՁϩδοΫΛ෼཭͍ͨ͠ • ͞Βʹม׵ޙʹධՁ͍ͨ͠ • ܕ͸อଘ͍ͨ͠

  38. ϓϩάϥϜม׵ Symantics ΠϯλϑΣʔε ධՁΠϯλϓϦλ ม׵ΠϯλϓϦλ

  39. ϓϩάϥϜม׵ ධՁΠϯλϓϦλ

  40. typed-finalϓϩάϥϜม׵ R(2) R ղऍ mul(add(int(2), int(0)),int(1)) ߲ ධՁ݁Ռ [Suzuki, Kiselyov

    and Yukiyoshi. (2016)][4]
  41. typed-finalϓϩάϥϜม׵ R(2) R ղऍ mul(int(2),in t(1)) Mul(Int(2), Int(1)) AddIdent(R) AddIdent


    ϑΝϯΫλ mul(add(int(2), int(0)),int(1)) ߲ ධՁ݁Ռ [Suzuki, Kiselyov and Yukiyoshi. (2016)][4]
  42. typed-finalϓϩάϥϜม׵ R(2) R ղऍ mul(int(2),in t(1)) Mul(Int(2), Int(1)) AddIdent(R) reflect

    reify AddIdent
 ϑΝϯΫλ mul(add(int(2), int(0)),int(1)) Ճ๏୯Ґݩنଇ ("%5 ߲ ධՁ݁Ռ [Suzuki, Kiselyov and Yukiyoshi. (2016)][4]
  43. typed-finalϓϩάϥϜม׵ R(2) R ղऍ int(2) Int(2) AddIdent(R) reflect reify AddIdent


    ϑΝϯΫλ add(int(2), int(0) Ճ๏୯Ґݩنଇ mul(add(int(2), int(0)),int(1)) Add(Int(2),Int(0)) MulIdent(AddIdent(R)) ... ... ... MulIdent
 ϑΝϯΫλ ৐๏୯Ґݩنଇ ("%5 ߲ ධՁ݁Ռ [Suzuki, Kiselyov and Yukiyoshi. (2016)][4]
  44. Normalization by Evaluation • reification • ҙຯΦϒδΣΫτ͔Β߲ͷਖ਼نతදݱΛநग़͢Δ ૢ࡞ • reflection

    • ߲ͷਖ਼نతදݱ͔ΒҙຯΦϒδΣΫτ΁ͷม׵ • reifyͷٯؔ਺ • ਖ਼نԽ • [Per Martin-Löf. (1975); Danvy and Filinski. (1990); Dybjer and Filinski. (2000)][5,6,7] etc
  45. typed-finalϓϩάϥϜม׵ R(2) R ղऍ int(2) ߲ ධՁ݁Ռ Int(2) AddIdent(R) reflect

    AddIdent
 ϑΝϯΫλ add(int(2), int(0) Ճ๏୯Ґݩنଇ mul(add(int(2), int(0)),int(1)) Add(Int(2),Int(0)) MulIdent(AddIdent(R)) ... ... ... MulIdent
 ϑΝϯΫλ ৐๏୯Ґݩنଇ reify reify
  46. typed-finalϓϩάϥϜม׵ R(2) R ղऍ int(2) ߲ ධՁ݁Ռ Int(2) AddIdent(R) reflect

    AddIdent
 ϑΝϯΫλ add(int(2), int(0) Ճ๏୯Ґݩنଇ mul(add(int(2), int(0)),int(1)) Add(Int(2),Int(0)) MulIdent(AddIdent(R)) ... ... ... MulIdent
 ϑΝϯΫλ ৐๏୯Ґݩنଇ reify reify ؍ଌ PCTFSWBUJPO
  47. GADT (Generalized Algebraic Data Types) • දݱܕΛGADTͰߏ੒ͨ͠ܕʹ͢Δ sealed trait Term[T]

    final case class Unknown[A](x: sym.Repr[A]) extends Term[A] final case class IntLit(e: Int) extends Term[Int] final case class Add(e1: Term[Int], e2: Term[Int]) extends Term[Int] type Repr[T] = Term[T] trait AddSym { type Repr[T] def int(n: Int): Repr[Int] def add(t1: Repr[Int], t2: Repr[Int]): Repr[Int] }
  48. දݱܕͷม׵ trait RR { import cats.~> type From[_] type To[_]

    // Term def fwd: From ~> To // reflection def bwd: To ~> From // reification def map[A, B](f: From[A] => From[B]): To[A] => To[B] = (t: To[A]) => fwd(f(bwd(t))) def map2[A, B, C](f: (From[A], From[B]) => From[C]): (To[A], To[B]) => To[C] = (t1: To[A], t2: To[B]) => fwd(f(bwd(t1), bwd(t2))) } R.Repr AddIdent(R).Repr MulIdent(AddIdent(R)) .Repr From To From To
  49. Reification and Reflection // AdditiveIdentity class AddIdent[FS <: AddMulSym](val sym:

    FS) { sealed trait Term[T] final case class Unknown[A](x: sym.Repr[A]) extends Term[A] final case class IntLit(e: Int) extends Term[Int] final case class Add(e1: Term[Int], e2: Term[Int]) extends Term[Int] object AddRR extends RR { override type From[T] = sym.Repr[T] override type To[T] = Term[T] def fwd: From ~> To = new (From ~> To) { def apply[A](x: sym.Repr[A]): Term[A] = Unknown(x) } def bwd: To ~> From = new (To ~> From) { def apply[A](term: Term[A]): sym.Repr[A] = term match { case Unknown(x) => x case IntLit(n) => sym.int(n) case Add(e1, e2) => sym.add(bwd(e1), bwd(e2)) } } } ...

  50. Reification and Reflection // AdditiveIdentity class AddIdent[FS <: AddMulSym](val sym:

    FS) { sealed trait Term[T] final case class Unknown[A](x: sym.Repr[A]) extends Term[A] final case class IntLit(e: Int) extends Term[Int] final case class Add(e1: Term[Int], e2: Term[Int]) extends Term[Int] object AddRR extends RR { override type From[T] = sym.Repr[T] override type To[T] = Term[T] def fwd: From ~> To = new (From ~> To) { def apply[A](x: sym.Repr[A]): Term[A] = Unknown(x) } def bwd: To ~> From = new (To ~> From) { def apply[A](term: Term[A]): sym.Repr[A] = term match { case Unknown(x) => x case IntLit(n) => sym.int(n) case Add(e1, e2) => sym.add(bwd(e1), bwd(e2)) } } } ...

  51. Reification and Reflection // AdditiveIdentity class AddIdent[FS <: AddMulSym](val sym:

    FS) { sealed trait Term[T] final case class Unknown[A](x: sym.Repr[A]) extends Term[A] final case class IntLit(e: Int) extends Term[Int] final case class Add(e1: Term[Int], e2: Term[Int]) extends Term[Int] object AddRR extends RR { override type From[T] = sym.Repr[T] override type To[T] = Term[T] def fwd: From ~> To = new (From ~> To) { def apply[A](x: sym.Repr[A]): Term[A] = Unknown(x) } def bwd: To ~> From = new (To ~> From) { def apply[A](term: Term[A]): sym.Repr[A] = term match { case Unknown(x) => x case IntLit(n) => sym.int(n) case Add(e1, e2) => sym.add(bwd(e1), bwd(e2)) } } } ...
 R.Repr AddIdent(R).Repr MulIdent(AddIdent(R)) .Repr From To From To
  52. GADTͱNbEͰܕอଘͭͭ͠ม׵ • GADTʹΑͬͯSymanticsͷܕʹै͏ class AddIdent[FS <: AddMulSym](val sym: FS) {

    ... val addIdentInterp = new GenericTrans(AddRR)(sym) { def add(t1: Term[Int], t2: Term[Int]): Term[Int] = (t1, t2) match { case (IntLit(0), _) => t2 case (_, IntLit(0)) => t1 case (_, _) => Add(t1, t2) } } } ࠨ୯Ґݩ ӈ୯Ґݩ
  53. typed-finalϓϩάϥϜม׵ R(2) R ղऍ int(2) ߲ ධՁ݁Ռ Int(2) AddIdent(R) reflect

    AddIdent
 ϑΝϯΫλ add(int(2), int(0) Ճ๏୯Ґݩنଇ mul(add(int(2), int(0)),int(1)) Add(Int(2),Int(0)) MulIdent(AddIdent(R)) ... ... ... MulIdent
 ϑΝϯΫλ ৐๏୯Ґݩنଇ reify reify ؍ଌ PCTFSWBUJPO
  54. typed-finalϓϩάϥϜม׵ R(2) R ղऍ int(2) ߲ ධՁ݁Ռ Int(2) AddIdent(R) reflect

    AddIdent
 ϑΝϯΫλ add(int(2), int(0) Ճ๏୯Ґݩنଇ mul(add(int(2), int(0)),int(1)) Add(Int(2),Int(0)) MulIdent(AddIdent(R)) ... ... ... MulIdent
 ϑΝϯΫλ ৐๏୯Ґݩنଇ reify reify ؍ଌ PCTFSWBUJPO ͦΕͧΕͷϞδϡʔϧ͸ 4ZNBOUJDTΛ९कͯ͠࿈࠯͢Δ
  55. typed-finalϓϩάϥϜม׵ R(2) R ղऍ int(2) ߲ ධՁ݁Ռ Int(2) AddIdent(R) reflect

    AddIdent
 ϑΝϯΫλ add(int(2), int(0) Ճ๏୯Ґݩنଇ mul(add(int(2), int(0)),int(1)) Add(Int(2),Int(0)) MulIdent(AddIdent(R)) ... ... ... MulIdent
 ϑΝϯΫλ ৐๏୯Ґݩنଇ reify reify ؍ଌ PCTFSWBUJPO
  56. typed-finalϓϩάϥϜม׵ R(2) R ղऍ int(2) ߲ ධՁ݁Ռ Int(2) AddIdent(R) reflect

    AddIdent
 ϑΝϯΫλ add(int(2), int(0) Ճ๏୯Ґݩنଇ mul(add(int(2), int(0)),int(1)) Add(Int(2),Int(0)) MulIdent(AddIdent(R)) ... ... ... MulIdent
 ϑΝϯΫλ ৐๏୯Ґݩنଇ reify reify ؍ଌ PCTFSWBUJPO ίʔυੜ੒ثΛ༩͑Δ ͜ͱ΋Ͱ͖Δ
  57. Finally, Tagless ҙ༁: ࠷ޙʹλά͕ͳ͚Ε͹͍͍ΑͶ

  58. typed-final

  59. [Suzuki, Kiselyov and Yukiyoshi. (2016)][4]

  60. ·ͱΊ

  61. ·ͱΊ • typed-final͸DSLΛߏங͢ΔΞϓϩʔν • දݱܕreprͰର৅֎ͷߏ੒ࢠ͕ೖΓࠐ·ͳ͍ Α͏ʹ͢Δ • GADTͱNbEతΞϓϩʔνΛซ༻͢Δ͜ͱͰɺ ܕΛอଘ͠ͳ͕Βfinal styleͰϓϩάϥϜม׵

    • tagless-final͸typed-finalʹͳͬͨ
  62. ࢀߟจݙ • [1] Jacques Carette, Oleg Kiselyov, and Chung-chieh Shan.

    2009. Finally tagless, partially evaluated: Tagless staged interpreters for simpler typed languages. J. Funct. Program. 19, 5 (September 2009), 509-543. • [2] Miller, Dale & Nadathur, Gopalan (1987) A logic programming approach to manipulating formulas and programs. In IEEE Symposium on Logic Programming, Seif Haridi (ed). Washington, DC: IEEE Comp. Society Press, pp. 379–388. • [3] Pfenning, Frank & Elliott, Conal (1988) Higher-order abstract syntax. In PLDI 88: Proceedings of the ACM Conference on Programming Language Design and Implementation. ACM SIGPLAN Notices, vol. 23(7). New York: ACM, pp. 199–208. • [4] Kenichi Suzuki, Oleg Kiselyov, and Yukiyoshi Kameyama. 2016. Finally, safely-extensible and efficient language-integrated query. PEPM '16. ACM, New York, NY, USA, 37-48. • [5] Per Martin-Löf. About models for intuitionistic type theories and the notion of definitional equality. In Proceedings of the Third Scandinavian Logic Symposium (1972), volume 82 of Studies in Logic and the Foundation of Mathematics, pages 81–109. North-Holland, 1975. • [6] Olivier Danvy and Andrzej Filinski. Abstracting control. In Mitchell Wand, editor, Proceedings of the 1990 ACM Conference on Lisp and Functional Programming, pages 151–160, Nice, France, June 1990. ACM Press • [7] Peter Dybjer and Andrzej Filinski. Normalization and partial evaluation. In Gilles Barthe, Peter Dybjer, Luís Pinto, and João Saraiva, editors, Applied Semantics – Advanced Lectures, number 2395 in Lecture Notes in Computer Science, pages 137–192, Caminha, Portugal, September 2000. Springer-Verlag.