VRのためにHaskellを使った話

Posted by Haruka Nakajima(@haru2036) on December 03, 2019Tags: Spock, VRChat

Link to
here
はじめに

はじめまして。趣味でHaskellしているはる(haru2036)と申します。まったり進行で開発しているのでGHCのバージョンアップの速さについていけてない感があります…… さて、今回はあんまり深い話はありません。どちらかと言うとこんなニッチなところにHaskell使ったよというネタで書きます。

Link to
here
VR空間でLTがしたい

突然ですが、私はVRChat(以下VRC)というソーシャルVRサービス(Second LifeVR版みたいなものです)にハマっています。
友人との雑談の中でVRCの中でLT会ができればプログラミングなどの話題で盛り上がれる人が集まってワイワイ楽しくできるのではないかと話して、その場のノリでとりあえず実装してみることにしました。

完成したワールド
完成したワールド

今回作りたかったのはスライドを表示するためのスクリーンと、ページ送りに使うボタンを実装したワールドです。

発表者用コントロールパネル
発表者用コントロールパネル

VRCではアバターやワールドを自由に作ることができるのですが、VRCが提供するコンポーネント以外のスクリプトは利用できません。Haskellユーザとしては得意なことを活用しづらい土壌です。
幸いスライドを表示する手段はゲーム内でURLから画像を取得し表示するVRC_Panoramaというコンポーネントを利用することにより確保できましたが、VRC_Panoramaが取得できる画像はワールド作成時に決め打ちで指定されたURLのリストに含まれるもののみです。
そのため、スライド画像へのURLのリストを直接VRC_Panoramaに渡していると、イベントを開催する際よくある飛び入り参加やスライドの用意が遅れた参加者に対応できなくなってしまいます。

その問題を解決するために、イベント開始時からのページ数とスライドの画像URLをマップするWebAPIを用意しました。
具体的には、/slides/{pageCount} のような形のエンドポイントを持ったAPIを用意し、そこから実際の画像へリダイレクトをかけるという方法を取りました。

実装イメージ図
実装イメージ図

Link to
here
Webフレームワーク

今回は自分で使うだけだしということでさらっとやってみたかったのでSpockを利用しました。もう少し誰でも使えるサービスにしたいと考えているのでServantに載せ替えてかっちり作り直そうかと思い移植しているところです。

Link to
here
はじめてのHaskellペアプロ

じつはLT会をやろうと思いついた友人のBOXPClojureユーザで、せっかくだからとAPIの開発を手伝ってくれました。
あまりHaskellに馴染みはなかったものの、いわゆる関数型プログラミング的な概念はバッチリなのでスススっと書いてくれました。
書いてくれる上での障壁になったのは、型関連の要素(datatypenewtypeがぱっと見わからなかった、型コンストラクタ、値コンストラクタの概念)に馴染みが薄かったことでした。
Discordで画面共有しながら説明を行ったのですが、やはり同じ画面を見ながら説明するのはとてもやりやすいと感じました。
本人からのメッセージはこちら。

プログラミングHaskellを昔読んでかじったことがある程度で素人もいいところでしたが、当人のサポートもあり思いついた数日後には実装が終わっていました。 はるくんの話にもある通りDiscordで画面共有しながらペアプロし、Haskellでのテストコードの書き方も一から教えてもらいながら書きました。これは願ってもない体験だったので根気よく教えてくれたことに非常に感謝しています。

また、個人的には実装以外でのブレストや実際の会場でのデバッグをVRChat上でできた事もとてもよかったなと思っています。 単純に実装を確認するためには二人以上でVRChatに入る必要があるというのもありましたが、完全リモートでも身振り手振りありでブレストができたことや、アバターのおかげで環境に囚われないコミュニケーションができていたこともGoodでした。

Link to
here
デプロイ

今回は自分で使うだけな上に常時稼働している必要もなく、コストを最小限に抑えたかったのでHerokuにデプロイしました。
Dockerfileを書き、スタティックリンク周りで悩みながらもイメージを生成してHerokuのレジストリにPushし、後はいつものHerokuという感じでうまくいきました。

余談ですが、最近参加したGotanda.hsというイベントでcabal build --enable-executable-staticでいい感じにシングルバイナリが生成できるというお話を聞いたので、最近stackばっかり使ってたのを改めて適材適所で使い分けていきたいなーと思っています。

Link to
here
実際に開催してみて

ここはHaskellほぼ全く関係ないですが……

VRC-LTという名前で6回ほど開催しているのですが、場所の制約を受けずに勉強会ができ、その後の懇親会も会場の撤収時刻や終電を気にせず話したい人はとことん話し続ける事ができるというところが非常に良かったです。
ホワイトボードはまだ未実装ですが、空間に書けるペンも配布されているのでその手のアイテムも取り入れれば懇親会での話も更にはずむのではないでしょうか。

VRChatPCのみでも利用することができます。 VRC-LTはほぼ月イチペースで不定期開催ですので、もしよろしければ参加していただけると嬉しいです。 開催時のアーカイブ等も以下のWebサイトにて公開中です。合わせてご覧ください。 https://vrc-lt.github.io

Link to
here
リポジトリ

そんなこんなで開発中のリポジトリはこちらになります。
拙いところもいっぱいですがIssuePRなどで気になった点を教えていただければ幸いです!
https://github.com/vrc-lt/VRC-Slide-Server