Haskellと共に4年間を歩んだ起業家の視点

(訳注:2016/9/28、頂きましたフィードバックを元に記事を修正いたしました。)

2012年、私は新しいタイプの企業向けeラーニングプラットフォームを開発するスタートアップ、Better1を共同設立しました。私たちのゴールは、大企業が、適応力の高いクロスプラットフォーム、多言語のオンラインコースを、速く安く開発、配信、解析できるようにすることでした。

立ち上げ初日にメインで使うと決めたHaskellは、チームが開発者10人を抱えるようになった時もバックエンドで使い続けていた唯一の言語でした。

実験と開発の期間を経て、Betterは数か月の間にAmerican ExpressやSwissportを始めとする顧客を得て、$0から$500,000超の年間経常利益を上げるまでに成長しました。しかし、更なる成長を目指すためには配信モデルが妨げになることが分かったため、最終的にオーストラリアのコンプライアンス企業、GRC Solutionsに売却しました。

Haskellへの関心は徐々に高まっているように見えますが、今もプロダクションではほとんど使われていません。アカデミックな言語以上のものではないと誤った思い込みをしている人もいます。この記事では、スタートアップでHaskellを使うとはどういうことなのか、私の考えを述べます。思いどおりに実装できるのか。実地でも問題なく使えるのか。Haskellを使える開発者は雇えるのか。今後使用する企業は増えるのか。

結論から言うと、答えはYesです。あらゆる問題の解決、全てのチームに適しているわけではありませんが、真剣に検討する価値はあります。サーバーサイドで実行するソフトウェアの構築を行う場合は、Haskellは今日探し得る中で最も秘密兵器に近いと言っていいかもしれません。2


注釈: 秘密兵器だって?

なぜHaskellを選んだのか?

Betterを立ち上げる数年前、私はある投資顧問企業の予測モデルを実装しました。Pythonで構築した最初のプロトタイプは脆弱でエラーが起こりやすいものでした。ある変数に常に金額の値を保持させ、その他の変数にはパーセンテージを確実に保持させるにはどうすればよいのか。関数内でオブジェクトの状態の突然変異を防ぐ方法はあるのか。それが、どれほど時間がかかって退屈でも、おびただしいテストを書く必要があるでしょう。

私は大学で学んだHaskellを思い出し、もう一度見直してみました。何日か実験した後、驚くことに予測モデルのタスクにより適しているころが分かり、1週間でモデルのラフバージョンを作り上げてしまいました。後にBetterを始めた時には、Haskellは他のどの一般的な言語よりも生産性が高い、と自信を持って言うことができました。

Haskellが多くの言語と異なるのは、その純粋性、遅延評価、そして強く静的な型推論システムです。純粋性のため、プログラムの論理づけが容易です。遅延評価は、関数合成と最適化に優れています(メモリプロファイルが理解しがたいという代償はあります)。強く静的な型推論は、軽量のメカニズムで整合性を強化し3、快適なリファクタリングを実現し、テストを書いたり維持したりせずとも大量のバグの類を排除します。これらの性質によって、非常に楽しく生産性の高い開発ができるのです。

思いどおりに実装できるのか?

ゼロから何かを作るなら、Haskellの利点は、かなり限られた知識で実装できるということです。出来上がりは特に整然としているわけでも効率的でもないでしょう。しかし、後になって5行のコードがすぐに再利用できる標準的な抽象化だと気付くはずです。

初心者にとってのマイナス面は、大きく生産性を上げようとするなら、学ばなければならないことが多いということです。それはベテラン開発者にとっても同様です。Haskellは概念や抽象化に重きを置いていますが、多くの場合、これらは言葉から受ける印象ほど難しくはありません。良い教科書もありますが、ブログ記事やレポートも重要な役割を担っています。人によって好みはありますが、その概念にはHaskellそのもの超えた価値があり、あなたの一般的なプログラム構築に対する考え方にも影響を与えるでしょう。それは面白いものです。

より実用的な点では、Haskellで私が最も不満なのは、基本的なツールのサポートです。cabal-installでの構築はスムーズではありませんでした。以降、Stackはこれらの懸念点の多くを改善してきました。 Stackは初心者にも使いやすく、大きなHaskellプロジェクトの管理をサポートしています。GitHubでライブラリをフォークしたり、パッケージをプッシュすることなくフォークに依存したり、多くの既存のツールチェーンで行っているのと同じように実装できます。

Haskellツールサポートは発展途上で、特にIDEとエディタはまだまだ理想的ではありません。いくつかのエディタを統合する設定はできますが、厄介で一般的ではありません4。とりわけ、Haskellの型情報がリッチで使い勝手が良いことを知っている身からすれば、これは残念なことです。

ライブラリについては、カバレッジはまともですがベストではありません。気付けば、よりポピュラーな言語であれば書く必要のないような内部ライブラリを書いていたりします(例えばMandrillのAPI経由でeメールを送る、など)5。Haskellには世界規模のライブラリがありますが、どれが良いのか判断するのは困難で6、それぞれの品質にはかなりバラつきがあります。私の記憶が正しければ深刻なライブラリのバグに見舞われたのは1度だけで、それはHTTPS接続ができないというものでした。7

言語そのものについて言うと、Haskellは遅延評価を行うので、他の言語よりも、空間計算量について考えなければなりません。サポートしてくれる良いツールやテクニックはあるので、それらによってメモリ効率の高いコードは書けますが、厳格な言語に比べると、かなり意識して作業する必要があります。より良いパワフルな抽象化が手に入るなら、多少の精神的負担には耐えられるでしょう。また、文字列型間の変換、標準スタイルや良いレコード構文がないなど、わずらわしいことは他にもあります。レコードの問題はLensで解決できますが、習得には時間がかかりますし8、デバッグも一筋縄ではいきません。

その他の点においては、日々使う分には、Haskellは驚くほど実用的です。Haskellのコードベースを、たとえリファクタリングや改良が恐ろしくなるような状態にしたかったとしても、まず不可能だと思うからです。型システムが役に立ちますし、言語が純粋なので、自信を持ってコードに理論づけできます。

Betterは、何度か大規模なリライトを経て大がかりなソフトウェアを作り上げました。私たちが市場を見誤ったのにも関わらず、エンジニアリングチームは一貫して成果を出し続けたのです。

ソフトウェアは問題なく使えるのか?

Betterのプラットフォームは、毎週約50万以上の学習アクションを処理しながら、1年以上もの間起動し続けてきましたが、その間、システムが停止したり、修理を行ったりしたことは1度もありません。バグ知らずといってもいいでしょう。その上、私たちは、プラットフォームの開発を止める直前に大幅なリファクタリングも行ったのです。

これは単なる事例証拠にすぎませんが、私が驚かされ、感心させられたのは、ソフトウェアが問題なく使えていたことです。エンジニアチームは素晴らしかったですし、ここまで成長できたのも彼らの功績が大部分と言えます。しかし私は、Haskellの功績も多少はあったと思っています。私たちはテスト駆動開発を行いませんでした。重要な部分にはテストを行ったものの、フルテストカバレッジと言えるようなものは行わなかったのです。その時はこれが、コストと質との正しいトレードオフだと思っていましたし、今でもその考えは変わっていません。

Haskellの型システムは、不一致を見つけるために、弱い型付けの言語で必要とされる大きなクラスのテストの必要性を取り除きます。このようなテストを最新に保ち続けることは、強固な型推論システムを持つことと比較すると、コスト面での負担が大きくなってしまいます。テスト駆動開発が、単にバグを見つけるために書くテストではないという意見があることは理解していますし、それが開発者にとって問題を見極め、明確な規律を推し進めることに役立つということも理解しています。しかし、Haskellは純粋な言語であって、このような規律や明瞭さの大部分をもたらしてくれる型だと思っています。「一度コンパイルしてしまえば、うまく機能する」と言うのも、真実味がありますね。

誤解のないように言っておきますが、私は、テストは重要だと考えています。ただ、型システムはある種の整合性を保証してくれますが、整合性のとれたプログラムも誤った動きをすることがあるのです。テストは、イテレーション速度と質とのトレードオフであって、異なるビジネスには異なるトレードオフを必要とします。

Haskellにはテストを行う際に使用できる素晴らしいツールがあります。例えば、QuickCheckは、関数を維持すべきと定義されたプロパティに基づいて、(Haskellの型システムを活用しながら)たくさんのランダムなテストケースを自動的に生成してくれます。

このように、Haskellは正確さや質を考えたソフトウェアには特にぴったりだと言えるでしょう。安全性のためにイテレーション速度が劣ってしまうと思うかもしれませんが、面白いことに、純粋ではない弱い型付けの言語よりもイテレーション速度が早くなることに気付くことでしょう。

Haskellを書く人材を雇用することができるか?

Betterの拠点はチューリッヒでした。起業した当初は、この地に知り合いはいなかったのですが、意外にも開発者の雇用は簡単でした。これも少なからず、Haskellのおかげです。人材雇用は労力のかかる仕事ですが、私たちが出会った多くの開発者は、Haskellに携わる仕事ができる、この可能性にワクワクしていました。最終的に、私たちは素晴らしいチームを作り上げることができたわけですが、中には、私たちと働くために海外からチューリッヒに引っ越してきたという人メンバーもいました。私たちの場合、初期の段階で、リモートチームは持たないと決めていたのですが、もし、あなたがリモート開発に積極的なのであれば、更にそういった選択肢を持ってもいいでしょう。

私たちは、役割ごとに、技術スキル、関心、モチベーションを持ち合わせた人物を雇い、そして高度なHaskellの知識を持つ人物を複数名、招き入れました。また、Haskellの知識が乏しい人材を雇用したこともいい経験になりました。開発者の1人は、物理学の学位を取得したばかりだったのですが、ベテラン開発者の指導を受けることで、すぐに生産性のある人材へとなっていたのです。

給与の面で言えば、私たちの会社は、GoogleやIBM、Zurich、その他の大手銀行には及びもしません。それでも私たちは、素晴らしい人材を手にすることができたのです。その要因の1つがHaskellです。優れた開発者は、優れた技術とともに仕事をすることに重きを置くようです。

企業文化への影響はどうか?

エンジニア文化におけるプログラミング言語の影響を、雇用決定や経営スタイル、個々の人柄などから分けて考えることは難しいと言えます。しかし、私はそれらのいくつかはHaskellの影響があると考えています。

人々は、給与の高い仕事を得るためにHaskellを学ぼうとはしません。そもそもHaskellの仕事はあまりないので、当然だとも言えます。それにこの言語は、他の言語に比べて学ぶのがより難しいと認識されているため、Functorやapplicative、monadといったおかしな名前の概念を学ぶことに気が進まない人は、この時点で省かれます。

この場合の利点としては、Haskellを学ぶことにある程度の時間を費やした人を雇う場合、彼らはソフトウェアを構築したり、新しいことを学んだりすることに平均以上の内発的動機付けを持っているということです。逆にマイナス面は、無意味な仕事や学ぶ機会が十分ではないことに嫌悪感を示す傾向にあります。

このように、Haskellを選んだことで、私たちが必要としていたエンジニア文化を築くことができましたが、これは魔法でも何でもありません。人材を雇用する際は慎重にプロセスを踏み、公平なマネージャーであろうと努めましたし、そしてあらゆる言語で素晴らしい開発を行える人材を探していました。

では、Haskellを使うべきか?

Haskellは万人向けというわけではありません。多くの開発者が慣れ親しんでいるものとは異なり、抽象的な概念を学ぶ必要があります。エコシステムは、他の一般的な言語のように洗練されていません。プロトタイプを2日間で書き上げられる最速の言語ではありません。ガベージコレクションがあるので、リアルタイムシステムには不向きですし、空間計算量はコロコロ変化します。またHaskellでのプロダクションを経験した人は、とても少ないのです。

しかし、これらが問題にならないのであれば、Haskellを楽しめるでしょう。Haskellは、小規模でスキルのある、成長過程にあるチームが、高品質のソフトウェアを速いイテレーションで構築するのに極めて優れた言語です。コードベースが拡大し、展開していったとしても、Haskellには複雑性を対処したり、考えを明らかにし、整合性を保証したりする嬉しい能力が備わっています。就寝する際に、サーバがクラッシュしてしまう心配もわずかで済みますし、古いコードにあるバグに費やす時間も少なくて済みます。また、自信を持って素早くリファクタリングができ、求人募集をする際にはJavaやNode、Rubyを扱う会社からも差別化を図ることができるでしょう。目新しくて、便利な抽象化概念のプログラム構築を考え始めるかもしれません。今の仕事が更に楽しくなるかもしれないということは、誰にも分かりません。

過去の話ですが、私はBetterでもっと違ったことができたのでは?と思うことがたくさんあります。ただし、Haskellを選択したことは、この中に入りません。

参考文献


  1. Betterという名前にはある思いが込められています。背景には私たちのユーザが、私たちのプラットフォームを使うことで、好転してほしいという思いがあるのです。私たちのスローガンは、「昨日よりもより良く」でした。とはいえ、社名がいくつかの混乱を招いたこともありましたし、妙な印象を与えたかもしれません。私たちの開発者の1人が、あるコンベンションでJony Lveに話しかけたそうです。聞いたところによると、JonyはBetterという社名を聞いてこう言ったそうです。「悪くなる可能性もあるよ」。 

  2. Paul Grahamは、彼が執筆したエッセイ『Beating the Averages(普通のやつらの上を行け)(編注:Shiro Kawai氏による和訳があります。以下の抜粋も同訳文より)の中で、Lispというニッチな言語についてこう語っています。

    Lispの何がそんなに素晴らしいんだ? それに、もしLispがそんなに良いのなら、 どうしてみんなそれを使わないんだ?これは修辞疑問みたいに聞こえるが、きちんとした答えのある質問だ。Lispは、信者のみが見ることができる魔法の特性があるから素晴らしいんじゃない。単に、今ある言語の中でもっともパワフルだからだ。そして、みんながそれを使わない理由は、プログラミング言語とは単なる技術だけでなく、心の習慣でもあり、それは最も変化の遅いものであるというものだ。もちろん、この二つの答えはもっとよく説明されなければなるまい。

  3. Haskellの型システムでは、プログラムが意図した通りに作動するという保証はありませんが、少なくとも文字列を乗算する、といったことは防いでくれます。 

  4. haskell-ide-engineはHaskell IDE向けの標準的なバックエンドを作成することを目的としていて、問題解決にあたってくれている人がいます。これは素晴らしいことです。 

  5. 私たちがMandrillライブラリを書いたすぐ後に、mandrillパッケージがリリースされました。 

  6. 高品質なライブラリを特定することで、そのライブラリを作成した著者や管理者を見分けられるようになるでしょう。Gabriel Gonzalezが執筆した『State of Haskell ecosystem』は、いかにHaskellとそのライブラリが異なる領域で安定しているかを理解するのに役立ちます。 

  7. 私たちが遭遇したライブラリのバグを調査した開発者が、Redditについて詳しく解説しています。どうやら今回も、Stackが私たちを救ってくれたようです。訂正:この記事の前のバージョンでは、私たちが遭遇したバグはtlsライブラリの中にあったと記述しましたが、Redditのコメントで説明しているように、これは誤りでした。 

  8. lensの学習曲線は急峻です。