日本ソフトウェア科学会第 37 回大会 (2020 年度) 講演論文集

外部データの解釈を文脈ごとに与える動的型付け機構
大堀 淳

上野 雄大

高城光平

近年急速に集積されつつある種々のデータは、それらを操作するプログラミング言語とは独立した意味と表現を持つ。これら外部データを静的型付き言語で取り扱うには，意図する処理に応じてデータを解釈し、言語の型システムでの表現に変換する必要がある。そこで必要とされる解釈と変換は、データを処理するアプリケーションに固有であり，さらに、データの処理文脈に依存する。本研究の目的は，外部データを静的型システムで表現可能な値に変換す動的型付け機構に、プログラマが意図する解釈に応じた変換処理を統合し、型付き言語における実用性の高い外部データ操作体系を確立することである。その第一歩として、外部データの対象を JSON 等の構造化データに限定し、我々がすでに実現している SML#の動的型検査構文に、型検査の対象となる外部データの変換処理をプログラムとして自由に指定できる言語機構を導入し拡張し、その実行性を確認した。本発表ではその概要を報告する。

プログラムが処理可能な内部データへ変換する必要

1 はじめにがある。この問題は、ビッグデータを扱うシステムなおよそ実用的なプログラムは、外部世界とのデーどで顕在化し始めているが、その系統的な手法は確タの入出力を必要とする。従来のシステムでは、外部立されていないと言える。現在の手法は、外部データデータは、それぞれのプログラミングシステムを念頭の処理の都合に合わせ、外部データを一旦、処理プロに用意され、プログラムから読み込まれ、利用されてグラムにとって都合のよい形式に変換し、変換されたきた。このモデルでは、外部データもプログラミング外部データを、従来の手法でプログラムが読み込み、のデータ同様、プログラムが定める解釈に従うデータ処理するというものである。

であり、プログラムが作り出すデータと同様の意味とこの外部データそのものを、事前にプログラムに合性質を持つ。そこでの技術的な課題は、多量のデータわせて変換する “データのクレンジング” アプローチを外部記憶装置に格納する方式や表現形態とその内は、従来の入出力処理を行うプログラムが、特的の目部形式への変換などであるが、これらは何れも、デー的で処理をするためには十分と思われるが、動的にタの入出力ライブラリ等の閉じた課題であり、プログ変化する外部データレポジトリをアクセスし、外部ラムの処理対象としてのデータは、あくまで従来プロデータの種々の側面をリアルタイムに分析するようなグラミング言語が扱ってきたデータ型であった。

システムの構築には十分に対応できないと思われる。

しかしながら、近年のデータサイエンスの隆盛に外部データの柔軟なアクセスには、外部データの意味より、種々のデータが、個々のプログラムとは独立にとその処理目的に従い、それぞれの処理コンポーネン集積され、それら集積されたデータの一部を個々のプトが、処理の文脈の応じて、外部データそのものを解ログラムがアクセスし、そのデータの意図に従って解釈し処理することが可能なプログラミング機能が必釈し処理することが必要となってきている。このた要と思われる。本研究の一般的な目的は、この洞察をめには、外部データを、その意図する意味に従って、下に、外部データの解釈を文脈ごとに与える機構を構

Atsushi Ohori, Katsuhiro Ueno, Kohei Takagi , 東北大学, Tohoku University.

築することである。この目的に向けて、外部データとして JSON のようなプログラミング言語に親和性のある構造データを対象とし、これら外部データを目的• reifiedTerm 表現を、JSON などの外部データに応じて柔軟にプログラムで処理する機構を試作しも表現可能に拡張し、外部データを reifiedTermた。本発表では、上述の目的を達成する上での技術的表現に変換する多相関数を提供する。

課題および試作の概要を報告する。

この機構によって、JSON などの構造データを動的にプログラミングに取り入れることが可能になった

2 基礎とするアプローチとその課題が、以下の未解決な問題が残っている。

外部データを JSON のような構造化データに限っ• 外部データは、独自の意味を持ったデータであても、プログラムで柔軟に処理できる機構は、従来り、プログラミング言語が定義する種々の制約さのプログラミング言語では十分にサポートされていれた型を表現するデータではない。従って、例えるとは言いがたい状況にある。現在のアプローチは、

ば数データは抽象的な数を表し、32 ビット整数構文解析ツールを用いて JSON データを構文解析し、や 64 ビット浮動小数点データではない。これら

JSON データそのものを表すデータ構造に変換し、そ基本データに限っても、用途に応じて、プログラのデータ構造を処理するアプローチである。このアプ
ローチでは、

val r = "{\"age\" : 25,ミング言語の型に変換する必要がある。

• 外部データには、いわゆる NULL 値が含まれている。データベース分野の長年の研究が明らかに\"name\" : \"Bowmore\",している通り、NULL 値の柔軟な扱いは、外部\"region\" : \"Islay\"}"データの扱いの鍵である。のようなデータは、例えば• 最近のデータクレンジング研究から明らかなよOBJ [("age", INT 25),

うに、それぞれの外部データは、その意味に応("name", STRING "Bowmore"),じた独自のフォーマットを採用している場合が多("region", STRING "Islay")]

く、複数の外部データの扱いには、これらフォーのような表現としてプログラムに与えられ、プログ
ラムが、"age"や"name"などの定性的な属性情報を含め、データとして処理する必要がある。

マットの差異を吸収する必要がある。
本研究の目的は、これら課題を解決し、型付き言語での実用性の高い外部データ操作体系を確立するこ

属性情報等を静的な情報として取り込む問題は、とである。この目的を達成するための第一歩として、

SML# の動的型付け機構 [1] によってほぼ解決されて前述の SML#の動的型付け機構を拡張し、これら問いる。例えば以下のようなプログラムが可能である。

題を解決する機構の構築を試みる。

# _dynamic Dynamic.fromJson r
as {age:int, name:string, region:string};
val it = {age = 25,

3 技術的課題とその解決戦略
これまでの分析から、本研究の具体的な課題は、外name = "Bowmore",

部データを処理の文脈に応じて解釈し変換する柔軟region = "Islay"}

な機構を、プログラミング言語の機能として提供する: {age: int, name: string, region: string}
このアプローチでは、以下のような機構で、外部データをプログラムで処理する。

ことである。
もちろん、任意のデータ変換をプログラムすることによって、個々のデータ変換は、当然実現可能であ• コンパイラは、言語がサポートする種々の型のる。データクレンジングアプローチは、外部データを値を、そのメタ情報も含むめて表現するデータ構

プログラムで処理する前に、その個々の必要な変換を造、reifiedTerm 表現を提供する。

ユーザが認識し、別なプログラムやツールなどによっ• さらに、型付きデータと reifiedTerm 表現とのて個別に変換を実行している。また、Python などの相互変換を行う機構をプログラマに提供する。

動的言語では、外部データを含むデータ構造を、動的な構造として保持し、外部データを含むすべてのデーとして記述し、コンパイラに、外部データの取りタを動的に処理するアプローチをとる。この場合は、込みの前に、この関数を外部データに適用する事プログラムがデータの構造の解釈を含む処理を行うを要求する。

ため、データ変換の問題は、限定的である。

さらに、この f の記述は、文脈に応じた NULL 値

我々が直面する課題は、静的に型付けられた言語の変換や、フォーマットの変換など、必要な変において、この変換を外部データの処理文脈と一体換パターンの集合として記述できることが望ま化し、例えば同一の外部データに対して、処理文脈しい。

によってそれぞれ必要な解釈変換を行う機構の構築

ガロア結合から、この関数 f から、以下の外部である。前節で述べた通り、静的に型付けられた言データ変換関数を得ることができる。

語では、例えば、int64 や real32 などの基本型や

f = λx : E.ψ(f (ϕ(x))) : E −→ E

{name:string, age:int} などの構造データは、そ• コンパイラは、具体的な外部データ E に以下のれぞれ独自の表現を持つ。プログラムが処理できる値変換を施し、プロフラムに提供する。

は、これら型で表現された値のみである。この構造かdaynamic f (E) as τら、プログラムの処理は、それらデータが内部の型に• 関数 f から f を生成する処理は、コンパイラ変換された後の値に限定される。われわれが必要とすが実現する必要があるが、必要な処理の構造は、る機能は、必要な時点で、それぞれの処理に必要な変SML#の関数を C 言語のデータに適用するため換をプログラムする機構である。の処理と同様に実現可能なはずである。そこで、この問題の系統的な解決を目指す上での我々の洞察とそれに基づく実現戦略は以下の通りである。

• プログラミング言語は、当然、種々のデータを任意に変更する関数を定義する機構を提供している。それら関数は、言語の型システム内部の変SML#コンパイラを拡張し、上記の機能を取り込んだ新たな以下の構文を提供する。

daynamic exp as τwith pat1 => exp1.
.
.

換として定義される。

| patn => expn

• プログラミング言語の型システムは十分に強力であり、外部データの構造を含む必要な構造も、もちろん型システムで表現可能である。

• 外部データの値の集合 E とプログラミング言語の型システムが定義する内部データの値の集合

D の間には、ガロア結合が構築可能である。
ϕ:E −→ Dψ:

D −→ E

この ϕ は、 dynamic e as τ などの変換と異なり、本来 ML の型として対応する値を持たない

NULL 値の表現なども含む ML の値への embedding であり、その定義は、コンパイラによって与えることができる。

• 外部データを利用するプログラマは、必要な変換を、プログラミング言語の内部データの変換関数

with 以下に書かれる規則は、種々の外部データの部分の変換規則を、SML#の世界で記述したものである。
コンパイラは、この規則を、適当な戦略で、可能な限り外部データのマッチする部分に適用し、外部データを変換した後、型 τ の値に変換する。

4 実装の概要
上述の洞察に基づき新しい構文を実装するためには、外部データの集合 E を具体的に定め、データ変換
関数 ϕ および ψ を実現した上で、関数 f を with 以下に書かれた変形規則の集合から生成する必要がある。
実装では、集合 E として、2 節で述べた reifiedTerm表現を用いた。この選択により、ϕ および ψ として、SML#コンパイラが動的型付け機構を実現するために提供しているプリミティブをほぼそのまま流用する

f : D −→ D

ことができる。SML#コンパイラは、reifiedTerm

fi が E に対して期待通り動作するためには、と ML の値を相互に変換する以下のプリミティブをϕ(E) の型が pati の型と等しくなければならな提供する。

い。この制約を fi を呼び出す前にチェックでき

reifiedTermToML : ∀α#reify. reifiedTerm → α

るように、pati の構造を動的なデータ構造とし: ∀α#reify. α → reifiedTermて取り出した（reify した）値 pati を fi とペア

toReifiedTerm

ここで #reify は、型インスタンスを動的なデータ構にする。

造として取り出す（reify する）必要があることを表• f を、pati および fi の集合（リスト）と外部デーすカインドである。NULL 値の取り扱いを除けば、

タ E の reifiedTerm 表現を受け取り、E の pati

reifiedTermToML が ϕ に、toReifiedTerm が ψ ににマッチする部分にできる限り fi を適用した結果それぞれ対応する。

を返すユーザーレベルの関数 rewriteTerm としreifiedTermToML を NULL 値を含む embeddingて実装する。コンパイラは rewriteTerm 関数をとするためには、外部データの NULL 値に対応する呼び出すコードを生成するのみとし、変換規則のML の値をひとつ定める必要がある。前節で述べた適用戦略やマッチする部分の探索は rewriteTerm通り、NULL 値は本来 ML で対応する値を持たないの実装に委ねる。

特殊な値である。しかし、データを変換する規則をコンパイル例を図 1 に示す。

表現する目的にその意味を限定するならば、NULL

rewriteTerm は以下の戦略で外部データを書き換

値は他のどの値とも異なる単独のシンボルとみなすえる。まず、いずれかの pati にマッチする最大の部ことができる。この考え方に従い、実装では、唯一分項を探す。これは、外部データの外側から順に、各の値構成子 null を持つ新しいデータ型 null を導入

i について pati にマッチするかどうかを検査するこ

し、値構成子 null が外部データの NULL 値に対応とで行う。次に、マッチした部分項を fi を適用したする ML の値となるように、reifiedTermToML およ結果した結果で置き換える。ただし、fi が Match 例

び toReifiedTerm を拡張した。

外を返した場合はマッチしなかったものとして扱う。

残る f は、引数 D を受け取り、with 以下に記述さ一度マッチし置き換えられた部分項は、それ以上マッれた変換規則を、可能な限り D のマッチする部分にチの対象としない。以上の処理を、いずれかの pati適用した結果を返す関数である。この振る舞いを静的にマッチする部分項がなくなるまで、外部データの構なコード生成によって実現することは容易ではない。

造に対して再帰的に繰り返す。

一方、D の reifiedTerm 表現を別の reifiedTerm

新しい構文の実行例を、SML#の対話セッション表現に変形するプログラムならば、ユーザーレベルのとして図 2 に示す。JSON データ j はオブジェクトプログラミングでも実現可能である。そこで、f を含のリストである。j の最初の要素は with の最初の変む関数 f を以下の方針で実装した。

形規則に、最後の要素の dept の値は最後の変形規• コンパイラは、with 以下に与えられた変形規則則にそれぞれマッチし、規則によって null は""に、

pati => expi それぞれについて、前節で述べたガ"Sendai"は"SDJ"にそれぞれ書き換えられる。最後

ロア接続の考え方に基づき、関数 fi : E → E を生に、書き換え結果を SML#のレコードのリストとし成する。fi は、与えられた引数 E 全体が pati にて読み込む。

マッチするとき、expi の評価結果の reifiedTerm表現を返す。そうでなければ Match 例外を発生

5 まとめさせる。fi は具体的には以下のコードである。

プログラムとは独立に集積された外部データをプ

fn x => toReifiedTerm(case reifiedTermToML x ofpati => expi )ログラムで処理するには、外部データを、その意図する意味に従って、プログラムが処理可能な内部データ

ソースコード:

open Dynamic
fn dyn => _dynamic dyn as {id:int, dept:string} list
with {id:int, dept=null} => {id=id, dept=""} | "Sendai" => "SDJ"
コンパイル結果:

fn dyn =>_dynamic rewriteTerm[(PATRECORD [("id", PATWILD (_reifyTy(int))), ("dept", PATNULL)],
fn x => toReifiedTerm (case reifiedTermToML x : {id:int, dept:null} of{id:int, dept=null} => {id=id, dept=""}),(PATWILD (_reifyTy(string)),
fn x => toReifiedTerm (case reifiedTermToML x : string of"Sendai" => "SDJ"))]dyn
as {id:int, dept:string} list
図1

datatype exp as τ with · · · 式のコンパイル例# open Dynamic;# fun f dyn = _dynamic dyn as {id:int, dept:string} list>

with {id:int, dept=null} => {id=id, dept=""} | "Sendai" => "SDJ";(interactive):2.12-3.75(144) Warning: match nonexhaustive"Sendai" => ...
# val f = fn : [’a. ’a dyn -> {dept: string, id: int} list
# val j = fromJson "[{\"id\":0, \"dept\":null},\>\ {\"id\":1, \"dept\":\"KIX\"},\>\ {\"id\":2, \"dept\":\"Sendai\"}]";

val j = _ : void dyn# f j;
val it = [{dept = "", id = 0}, {dept = "KIX", id = 1}, {dept = "SDJ", id = 2}]: {dept: string, id: int} list
図2

datatype exp as τ with · · · 式の実行例へ変換する必要がある。本報告では、静的型付き言語

SML#において、外部データと SML#の値とのガロア結合を考え、外部データの一部を SML#の世界での課題や展望を明らかにする予定である。
謝辞 本研究の一部は JSPS 科研費 18K11233 および 19K11893 の助成を受けたものです。

書き換える規則を与えることで、外部データの処理文脈に応じてそれぞれ必要な解釈変換を行う言語機構

参 考 文 献を提案し、その試作について報告した。今後は、この[1] 大堀 淳, 上野 雄大. SML#の動的型付け機構. In 日
本ソフトウェア科学会第 36 回大会論文集, 2019.

試作を通じて、本研究が提案するアプローチの実用上