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

C#における Algebraic Eﬀects の実装の試み
野口 龍 松本 倫子

吉田 紀彦

関数型言語において計算的効果を扱うための手法である Algebraic Eﬀects の処理のモジュール化と再利用性に着目して，オブジェクト指向言語へ Algebraic Eﬀects を適用する研究がなされている．しかし，まだその例は少なく，また，その手法も様々である．本研究では Algebraic Eﬀects のオブジェクト指向言語への幅広い適用性を検討する
ため，C# においてライブラリとして Algebraic Eﬀects の実装を試み，例外処理などにおける Algebraic Eﬀectsの有用性を検討した．本発表では実装したライブラリの概要について報告する．

1 はじめに2 関連研究

オブジェクト指向言語は主にクラスをベースにモ

Algebraic Eﬀects は計算的効果をシグネチャとハジュール化を行うプログラミングパラダイムである．

ンドラに分けて記述する．Algebraic Eﬀects のライ

しかし，例外処理をはじめ従来のクラスではモジューブラリを開発する際にはこの 2 要素に加えハンドラル化が難しい処理が存在する．

内部で用いられる限定継続について考える必要があ

Algebraic Eﬀects は関数型言語において例外処理る．特に限定継続はオブジェクト指向言語とはあまりや IO などの計算的効果を取り扱う手法として，モ馴染みがない概念であるため実装の障壁となる要素ナドに代わるものとして注目されている．Algebraic

である．

Eﬀects では例外処理を始めとした計算的効果をシグネチャとハンドラに分けて取り扱うが，これがモジュール化と再利用性を高めている．

Algebraic Eﬀects が持つ柔軟なモジュール化と再利用性に着目して，Algebraic Eﬀects をオブジェク

Eﬀ [1] は Algebraic Eﬀect の研究用に開発された関数型言語で OCaml で実装されている．

JEﬀ [2] は Algebraic Eﬀect をオブジェクト指向言語に取り入れるために考案されたオブジェクト指向言語で実験的な実装がある．

ト指向言語に取り入れる試みが行われている．しかLua での実装である eﬀ.lua [3] では限定継続を Lua

し，例は少なく，またその実装方法も様々である．に備わっているコルーチンで実装している．コルーチ

本研究ではオブジェクト指向言語全般への幅広いンによる限定継続の実装はハンドラ内での限定継続適用性を検証する一助となるべく C# に焦点を当て呼び出しが一回限り（ワンショット）であるという制てライブラリとして Algebraic Eﬀects を部分的に実約があり，それにより非決定計算を記述できないなど装し，それを用いて例外処理などの計算的効果をモの欠点があるが，例外処理や IO などでは依然有用でジュール化することを試みた．本発表では本ライブラある．また，限定継続にコルーチンを利用したものとリの概要について報告する．

して，Lua よりもコルーチンの呼び出しに関する制約が強い JavaScript においても実装が見られる [4]．

An Attempt to Implement Algebraic Eﬀects in C#Ryu Noguchi, Noriko Matsumoto, Yoshihiko Yoshida,
埼玉大学, Saitama University.

Java での実装 [5] は多相型を基本とした静的型付け言語の利点を損なわない型設計を行っている．シグネ

チャをインターフェースとして表現し，ハンドラをシ関数内での計算的効果の利用が困難であることを意味

グネチャを継承したクラスで表現する．ただし限定継する. Lua のコルーチンは stackfull コルーチンであ続は予め印をつけた関数をコンパイルして得られたるため，このような問題がない．なお， JavaScript

JVM のバイトコードを後処理して実現しておりライのコルーチンも stackless コルーチンであるが，yieldブラリ単体として提供することは難しい．その代わりが値を返せるため引数で計算的効果を発生させるこ

ワンショットの制約はなく非決定計算などより多くのとができ，C# のコルーチンとは自由度が異なる．

計算的効果を扱うことができる．

最後は静的型付け言語特有の型の記述の煩雑さで特殊なものとしてオブジェクト指向言語と関数型言ある．C# では特別な戻り値の型である場合のみその語の両方の性質を持つ Scala にて実装された事例 [6]メソッドをコルーチンとみなす．この型は継承によるがあるが，限定継続がモナドで実現されており Java

別名がつけられないので略記ができずメソッドのシグや C# のようなモナドが提供されていない言語で同ネチャの記述が煩雑になる問題がある．

じようなアプローチをするのは難しい．
ほかにも C 言語で longjump を応用した実装が存在する [7]．

これらの問題点を受け入れ，ナイーブに実装する方針も考えられるが，本研究では限定継続の実装に関するコルーチンの利用方法を改変することによりこれらの問題を低減することを試みた．この改変の詳細及び

3 C# での実装の方針

それによる悪影響については 4 節にて詳しく述べる．

関連研究を踏まえて，本研究ではこれまで実装が試計算的効果のシグネチャとハンドラの記述の実装のみられていない C# を取り上げた． C# を特に取り方針については，クラス型オブジェクト指向言語とし上げた理由として，Unity [8] を初めとしたプロダクての特徴を活かすべく，本研究では Lua のものではトで採用されている実績があり，実装した際の有用度なく Java での実装で用いられたインターフェースにが高い言語であることが挙げられる．

よるシグネチャ記述とクラス拡張によるハンドラ記述

また，本研究ではユーザビリティを考えライブラの手法を応用する．ただし，後述するように perform

リ単体で Algebraic Eﬀects を実装することを目標と操作に相当するインターフェースとハンドラ内部のロした． そのため C# と類似の特徴を持つ Java でのジックと型設計は独自に行う必要があった．

先行研究の実装を移植することはできず，他の手法を用いて実装する必要がある．本研究では C# に備

4 ライブラリの実装

わっているコルーチンに着目し，限定継続の実装に以上の方針を踏まえて具体的な実装方法についてLua での実装で用いられていた手法を応用した． し述べる．はじめに限定継続の実装について述べる．前かし，C# のコルーチンは Lua のものとは異なる箇述の通り C# のコルーチンには限定継続を実現する所があり，Algebraic Eﬀects を実装する障壁となる際にユーザビリティを大きく低下させる問題がある．

点がある．

本ライブラリではこの問題を低減させるためにコルー

1 つめは処理の移譲を行う yield が値を返さないこ

チンの呼び出しと被呼び出しの関係を入れ替えた．つとである．yield は計算的効果を発生させるために用まり，計算的効果のハンドラがコルーチンとして計算いる perform を実装するために利用するが，C# の的効果を利用しているメイン処理を呼び出していた

yield では戻り値のある計算的効果を扱うことができのに対し，本ライブラリではメイン処理からコルーチない．これは復帰可能な例外処理や IO を取り扱う際ンとして計算的効果を呼び出している．これにより計に障害となる．

算的効果を単なるメソッドとして扱うことができ戻り

2 つ目は C# のコルーチンがスタックをまたいで値を扱ったり深いスタックからの呼び出しを行うことyield を行うことができない stackless コルーチンでができた．しかし，この方法では限定継続の破棄によあることである．これはコルーチン内部で呼び出したるスタックの破棄ができない．そこで本ライブラリではスタックの破棄を例外をスローすることにより実現

return a / b;

した．また，関係入れ替えたため前述の問題が今度は}ハンドラ内の処理に現れる．しかし，ハンドラの記述// エントリポイント
int Main(string[] args){// Handle メソッド// 処理とハンドラを渡して// 計算的効果を扱う
var result = EffectNet.Handle<int,int,MyExceptionHandler>(new MyExceptionHandler(),(exc, p) => SafeDivide(2, 0, exc, p));}は本処理の記述より少ないため問題が少ないと見られる．
次にシグネチャとハンドラの実装について述べる．
前述のようにシグネチャとハンドラは静的型を割り当てる必要があり，Java での実装を参考にした．ただし，限定継続の実装方法が異なるため一部の型は独自に用意した．

5 ライブラリの適用例
以下は本ライブラリによって実装した例外処理である．このように try-catch の catch 節の内容をクラスに閉じ込め再利用することができる．
// 計算的効果のシグネチャ
interface IException<TRes>{// 計算的効果はコルーチン
IEnumerator<Effect<TRes>>
Throw(string message);}// ハンドラclass MyExceptionHandler : IException<Void>,Handler<int,int?>{
public int? Pure(int pure){
return pure;}public IEnumerator<Effect<Void>> Throw(stringmessage){
Console.WriteLine(message);// 継続の破棄// 続く処理を中断する
yield return Return<int?>(null);}}// 計算的効果を扱うメソッド
int SafeDivide(int a, int b,IException<Void> exc, Performer p){if (b == 0) {p.Perform(exc("divide␣by␣zero"));}6 おわりに
本研究では Algebraic Eﬀects のオブジェクト指向
言語における広い適用性と有用性を検討するため，

C# において Algebraic Eﬀects を実装することを試みた．結果，限定継続がワンショットであること，継続の破棄が標準の例外機構に依存していることなど不完全な箇所があるが，Algebraic Eﬀects を C# のライブラリとして部分的に実装することができ，例外処理などにおいてその有用性を検討することができた．
今後の研究として，今回導入した限定継続の実装手法の改良や形式的記述，そして異なるアプローチを視野に入れた実装手法の検討を行いたい．

参 考 文 献[1] Eﬀ. https://www.eﬀ-lang.org.
[2] Pablo Inostroza and Tijs van der Storm. JEﬀ:
Objects for Eﬀect. Onward! 2018 Proceedings ofthe 2018 ACM SIGPLAN International Symposium
on New Ideas, New Paradigms, and Reﬂections on
Programming and Software, November 2018.
[3] eﬀ.lua. https://github.com/Nymphium/eﬀ.lua.
[4] eﬀ.js. https://github.com/MakeNowJust/eﬀ.js.
[5] Jonathan Immanuel Brachthäuser, Philipp Schuster, and Klaus Ostermann. Eﬀect Handlers for theMasses. Proceedings of the ACM on Programming
Languages, November 2018.
[6] Jonathan Immanuel Brachthäuser and PhilippSchuster. Eﬀekt: Extensible Algebraic Eﬀects inScala. Proceedings of 8th ACM SIGPLAN International Scala Symposium, October 2017.
[7] Daan Leijen. Implementing Algebraic Eﬀects in C
”Monads for Free in C”. Microsoft Research Technical Report, 2017.
[8] Unity. https://unity.com.