ghcs extensionsGADTs
とを使用した固定長ベクトルの次の定義がTypeOperators
ありDataKinds
ます。
data Vec n a where
T :: Vec VZero a
(:.) :: a -> Vec n a -> Vec (VSucc n) a
infixr 3 :.
data VNat = VZero | VSucc VNat -- ... promoting Kind VNat
type T1 = VSucc VZero
type T2 = VSucc T1
および TypeOperator の次の定義:+
:
type family (n::VNat) :+ (m::VNat) :: VNat
type instance VZero :+ n = n
type instance VSucc n :+ m = VSucc (n :+ m)
意図したライブラリ全体を意味のあるものにするために、タイプの固定長ベクトル関数を(Vec n b)->(Vec m b)
より長いベクトルの最初の部分に適用する必要がありますVec (n:+k) b
。その関数を と呼びましょうprefixApp
。タイプが必要です
prefixApp :: ((Vec n b)->(Vec m b)) -> (Vec (n:+k) b) -> (Vec (m:+k) b)
change2
次のように定義され た fixed-length-vector-function を使用したアプリケーションの例を次に示します。
change2 :: Vec T2 a -> Vec T2 a
change2 (x :. y :. T) = (y :. x :. T)
prefixApp
change2
長さ >=2 の任意のベクトルのプレフィックスに適用できる必要があります。
Vector> prefixApp change2 (1 :. 2 :. 3 :. 4:. T)
(2 :. 1 :. 3 :. 4 :. T)
実装方法を知っている人はいますprefixApp
か? (問題は、固定長ベクトル関数の型の一部を使用して、正しいサイズのプレフィックスを取得する必要があることです...)
編集: Daniel Wagners (非常に賢い!) ソリューションは、ghc 7.6 のリリース候補 (公式リリースではありません!) で機能したようです。ただし、私見では、次の 2 つの理由で機能しないはずです。
- の型宣言には、コンテキストに がありません (
prefixApp
正しく型チェックするため。VNum m
prepend (f b)
- さらに問題: ghc 7.4.2 は、TypeOperator
:+
が最初の引数 (2 番目の引数も同様ですが、ここでは必須ではありません) で単射であると想定していないため、型エラーが発生します: 型宣言からvec
、 typeVec (n:+k) a
であり、型チェッカーはsplit vec
、定義の右側にある式の型を推論しVec (n:+k0) a
ます。しかし、タイプチェッカーはそれを推測できません(単射であるk ~ k0
という保証がないため)。:+
この2番目の問題の解決策を知っている人はいますか? :+
最初の引数で単射であることを宣言するにはどうすればよいですか?また、この問題に遭遇しないようにするにはどうすればよいですか?