2009-04-20 [長年日記]
λ. 長さ付きリストに対する型安全な filter 関数
型レベルプログラミングの会(ヒビルテ(2009-04-18))の会場で出てた話だけど、(a → Bool) → Vec a n → (∃m≦n. Vec a m) みたいなやつなら定義可能。
{-# LANGUAGE EmptyDataDecls, GADTs, FlexibleInstances, MultiParamTypeClasses, IncoherentInstances #-} data Z data S n data Vec a n where VNil :: Vec a Z VCons :: a -> Vec a n -> Vec a (S n) class LE a b -- one definition of ordering instance LE Z n instance LE n m => LE (S n) (S m) -- another definition of ordering instance LE n n instance LE n m => LE n (S m) data BoundedVec a n where Bounded :: LE m n => !(Vec a m) -> BoundedVec a n vfilter :: (a -> Bool) -> Vec a n -> BoundedVec a n vfilter f xs = case xs of VNil -> Bounded VNil VCons x xs -> case vfilter f xs of Bounded ys -> if f x then Bounded (VCons x ys) else Bounded ys
ただ、Haskellの型クラスだと推論を制御するのが難しくて、オーバーラップしたインスタンス定義(IncoherentInstances)が必要になってしまった*1。 オーバーラップしたインスタンス定義を使わない定義は型ハッカーの諸氏への課題ということで。
*1 Agdaだと明示的に書くのでどうとでもなるのだけど、Haskellだと型クラスの機構を使って間接的に書かなくてはいけないのが、隔靴掻痒な感じだなぁ。