、ここでは1つのリストは、別の順列であることを証明しているデータ型は次のとおりです。Permutation
で証明可能正しい順列Haskellで書かれた(N^2)
data Belongs (x :: k) (ys :: [k]) (zs :: [k]) where
BelongsHere :: Belongs x xs (x ': xs)
BelongsThere :: Belongs x xs xys -> Belongs x (y ': xs) (y ': xys)
data Permutation (xs :: [k]) (ys :: [k]) where
PermutationEmpty :: Permutation '[] '[]
PermutationCons :: Belongs x ys xys -> Permutation xs ys -> Permutation (x ': xs) xys
、我々は並び替えるできるようになりましたレコード:
data Rec :: (u -> *) -> [u] -> * where
RNil :: Rec f '[]
(:&) :: !(f r) -> !(Rec f rs) -> Rec f (r ': rs)
insertRecord :: Belongs x ys zs -> f x -> Rec f ys -> Rec f zs
insertRecord BelongsHere v rs = v :& rs
insertRecord (BelongsThere b) v (r :& rs) = r :& insertRecord b v rs
permute :: Permutation xs ys -> Rec f xs -> Rec f ys
permute PermutationEmpty RNil = RNil
permute (PermutationCons b pnext) (r :& rs) = insertRecord b r (permute pnext rs)
これは問題なく動作します。ただし、permuteはO(n^2)
です。ここで、n
はレコードの長さです。順列を表現するために別のデータ型を使用することで、それをもっと速くする方法があるのだろうかと思います。可変と型なしの設定では比較のために
O(n)
時にこのような異種のレコードに並べ替えを適用することができます。レコードは値の配列として表現し、置換は新しい位置の配列として表します(重複は許されず、すべての数字は0とnの間でなければなりません)。順列を適用することは、その配列を繰り返し、それらの位置を持つレコードの配列にインデックスを付けることです。
より厳密に型指定された設定でO(n)
の順列が可能であるとは思っていません。でも、O(n*log(n))
のように見えるかもしれません。私はフィードバックを感謝し、私は何かを明確にする必要がある場合はお知らせください。また、これに対する答えは、コミュニケーションがより簡単に感じられることに応じて、Haskell、Agda、またはIdrisを使用することができます。
これはcs.stackexchange.com –
でこれを聞いたほうが良いかもしれません。私はこのようなコードを非常に頻繁に使用しているわけではありませんので、上記を推論するのが難しいですが、GHCがタイプチェックできるコンパイル時にすべてを評価するわけではありません。 – jberryman
これを達成するために、おそらくO(1)依存配列 'Array [k]'が必要です。とにかく、完全に依存するシステムでは、順列(位置配列として)とそれが2つのリストと関連していることを証明することができます。並べ替えを適用するには、あなたが言及している単純なO(n)アルゴリズムを使用します。おそらく、GADT、タイプレベルのナット、シングルトンで同じことをすることができます。 – chi