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. 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)
  2. 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 } } }
  3. 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] ... }
  4. 8.

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

    HOAS (ߴ֊ந৅ߏจ) ͕࢖͑Δ • ϝλݴޠʹΑͬͯείʔϓ҆શੑ͕୲อ͞ΕΔ • ݴޠίϯϙʔωϯτͷ߹੒Λαϙʔτ • ύʔαΛ࡞Βͳͯ͘Α͍ • ϗετݴޠͷΤίγεςϜ͕࢖͑Δ [J. Carette, O. Kiselyov and C.-c. Shan. (2009)] [1]
  5. 9.
  6. 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] }
  7. 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
  8. 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
  9. 14.

    Symantics • syntaxͱtyping rulesΛؔ਺ͷγάχνϟͰද͢ • දݱܕ (representation type) Ͱܕ෇͚نଇΛ ද͢

    • ߴ֊ΧΠϯυΛ࢖͏ • polymorphic lifting ͸࢖Θͳ͍ • semantics Λؔ਺ͷ࣮૷Ͱද͢
  10. 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)) } ΠϯλϓϦλʢ࣮૷ʣʹ ґଘ͠ͳ͍Ϣʔβϓϩά ϥϜ͕هड़Ͱ͖Δ
  11. 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] } ܕ͕อଘ͞ΕΔ ධՁؔ਺
  12. 17.

    ಈ͔͢ object test { val evaluator = Run.interp val p1

    = new Program(evaluator) def main(args: Array[String]) = { println("---------------------------------") println(evaluator.eval(p1.ex1)) // => 1 }
  13. 18.

    HOASͰλந৅Λѻ͏ • HOAS (Higher-Order Abstract Syntax; ߴ֊ந৅ߏจ) • ม਺ଋറΛϗετݴޠͷλͰදݱ͢ΔςΫχοΫ •

    ม਺Λਖ਼֬ʹѻ͏ͷ͸ׂͱ໘౗ • ม਺໊͕ඃΒͳ͍Α͏ʹ͢Δ • de Bruijn ΠϯσοΫεΛ࢖͏৔߹Ͱ΋ɺ୅ೖૢ࡞࣌ͷΠ ϯσοΫεͷγϑτܭࢉ͸ඞཁ • capture-avoiding substitution [Miller and Nadathur (1987); Pfenning and Elliott. (1988)][2,3]
  14. 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>
  15. 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>
  16. 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))
  17. 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))
  18. 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))
  19. 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))
  20. 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))
  21. 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
  22. 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]
  23. 32.

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

    ӈ୯Ґݩ • 0 + m = m ... ࠨ୯Ґݩ • tagless-final͸ؔ਺ʹΑͬͯݴޠΛߏ੒͢Δ • ؔ਺Ͱߏ੒͞ΕͨϓϩάϥϜΛͲͷΑ͏ʹม׵͢Δ͔ val program: R[Int] = add(int(1), int(0))
  24. 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]
  25. 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]
  26. 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]
  27. 44.

    Normalization by Evaluation • reification • ҙຯΦϒδΣΫτ͔Β߲ͷਖ਼نతදݱΛநग़͢Δ ૢ࡞ • reflection

    • ߲ͷਖ਼نతදݱ͔ΒҙຯΦϒδΣΫτ΁ͷม׵ • reifyͷٯؔ਺ • ਖ਼نԽ • [Per Martin-Löf. (1975); Danvy and Filinski. (1990); Dybjer and Filinski. (2000)][5,6,7] etc
  28. 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
  29. 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
  30. 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] }
  31. 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
  32. 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)) } } } ...

  33. 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)) } } } ...

  34. 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
  35. 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) } } } ࠨ୯Ґݩ ӈ୯Ґݩ
  36. 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
  37. 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Λ९कͯ͠࿈࠯͢Δ
  38. 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
  39. 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 ίʔυੜ੒ثΛ༩͑Δ ͜ͱ΋Ͱ͖Δ
  40. 60.
  41. 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.