TypeFamilyDependenciesの実用的な例を考える
FunctionalDependenciesというGHC言語拡張がある.Haskell Wikiによると,
Functional dependencies are used to constrain the parameters of type classes.
と書かれているが,これはどういうことか.
Haskell Language Reportで定められた範囲では,型クラスに与えられるパラメータは1つに限られるが,MultiParamTypeClassesを用いると,複数のパラメータを与えることができる.この際に,パラメータとして与えられた(複数の)型の間の関係性に制限を加えることができるのが,FunctionalDependenciesなのであった.恐らく多くの人が初めて目にするのは,mtl packageのMonadReaderの定義なのではないだろうか.| m -> rというのがそれである.
class Monad m => MonadReader r m | m -> r where
...
さて,GHC 8からTypeFamilyDependenciesというGHC言語拡張が追加された.これについては既にlotz先生が『型族が単射だと嬉しい理由』という記事を書いていらっしゃるのだが,(氏には失礼ながら)少しばかりわざとらしい例だと感じたので,もう少し実務的な例を引き合いに出して,有用性を示したいと思う.
Template Haskellでコード中にJSONを埋め込んだりコンパイル時にファイルから型安全に読み込んだりする
Template Haskellでコンパイル時FizzBuzz
数ヶ月前にTwitterで,コンパイル時にFizzBuzzを計算して,実行時には計算された文字列を出力をするだけ,というコンパイル時FizzBuzzを何かの言語でやっているのを見かけた.元ネタは江添さんがC++で書いたものらしい.インスピレーションを受けて,Haskellで書いてはみたが,簡単すぎて全然おもしろくなくなってしまった.
Type-level TypeScript
この記事はCAMPHOR- Advent Calendar 2017の21日目の記事です.
12月といえば,万人受けしなさそうなネタでブログを書いては「はてブが付かねえ」と文句を言う季節だが,今年もそういう方針で,TypeScriptでの型レヴェル計算について書く.型レヴェルでの自然数などが定義できると,リストに型レヴェルで長さを付けることができて,空リストの先頭の要素を取ろうとしてランタイムで落ちる,という悲劇が生じる可能性をコンパイル時に排除できてとても嬉しい*1.
なお,使用しているTypeScriptのヴァージョンは,少し古くて2.4.1である.これは,手元でたまたま2.6系のプロジェクトと2.4系のプロジェクトがあったのだが,2.6系だと型推論が停止しない(tscが"Maximum call stack size exceeded"で死ぬ)ことに気付き,悲しい気持ちになったからである.