私はHaskellの依存型プログラムの例で作業していますが、という定義命題型の証拠をsingletonsライブラリに定義して "書き直したい"と思います。Haskellで依存型プログラミングの問題
具体的には、正規表現メンバーシップの証拠を表すデータ型があります。私の問題は、2つの正規表現を連結した証拠をどう扱うかです。私のコードではInRegExp xs e
と呼ばれるGADTを持っていて、xs
は正規表現の言語であるe
であることを表しています。連結のために、私は次のコンストラクタを持っています:
InCat :: InRegExp xs l -> InRegExp ys r ->
(zs :~: xs ++ ys) -> InRegExp zs (Cat l r)
これまでのところ、とても良いです。今私は2つの正規表現の連結のメンバーシップのために反転補題を定義したい:
inCatInv :: InRegExp (xs ++ ys) (Cat e e') -> (InRegExp xs e , InRegExp ys e')
inCatInv (InCat p p' Refl) = (p , p')
が、コードは、次のエラーメッセージでGHCによって拒否された:Agdaまたはイドリスで
Could not deduce (xs1 ~ xs)
from the context ('Cat e e' ~ 'Cat l r)
bound by a pattern with constructor
InCat :: forall (zs :: [Nat])
(xs :: [Nat])
(l :: RegExp [Nat])
(ys :: [Nat])
(r :: RegExp [Nat]).
InRegExp xs l
-> InRegExp ys r -> zs :~: (xs ++ ys) -> InRegExp zs ('Cat l r),
in an equation for ‘inCatInv’
at /Users/rodrigo/Dropbox/projects/haskell/experiments/src/Lib.hs:44:11-25
or from ((xs ++ ys) ~ (xs1 ++ ys1))
bound by a pattern with constructor
Refl :: forall (k :: BOX) (b :: k). b :~: b,
in an equation for ‘inCatInv’
at /Users/rodrigo/Dropbox/projects/haskell/experiments/src/Lib.hs:44:22-25
‘xs1’ is a rigid type variable bound by
a pattern with constructor
InCat :: forall (zs :: [Nat])
(xs :: [Nat])
(l :: RegExp [Nat])
(ys :: [Nat])
(r :: RegExp [Nat]).
InRegExp xs l
-> InRegExp ys r -> zs :~: (xs ++ ys) -> InRegExp zs ('Cat l r),
in an equation for ‘inCatInv’
at /Users/rodrigo/Dropbox/projects/haskell/experiments/src/Lib.hs:44:11
‘xs’ is a rigid type variable bound by
the type signature for
inCatInv :: InRegExp (xs ++ ys) ('Cat e e')
-> (InRegExp xs e, InRegExp ys e')
at /Users/rodrigo/Dropbox/projects/haskell/experiments/src/Lib.hs:43:13
Expected type: InRegExp xs e
Actual type: InRegExp xs1 l
Relevant bindings include
p :: InRegExp xs1 l
(bound at /Users/rodrigo/Dropbox/projects/haskell/experiments/src/Lib.hs:44:17)
inCatInv :: InRegExp (xs ++ ys) ('Cat e e')
-> (InRegExp xs e, InRegExp ys e')
(bound at /Users/rodrigo/Dropbox/projects/haskell/experiments/src/Lib.hs:44:1)
In the expression: p
In the expression: (p, p')
、この一種の反転補助定理はうまく動作します。ハスケルでそのような補題を表現することは可能ですか?完全コードは、gistで利用可能です。
このような補題をどのように表現することができるのか、それが表現できないのかについてのヒントや説明は高く評価されます。
問題は、非注入型のファミリーです。残念ながら、これを回避するための簡単な方法はありません。基本的に '(xs ++ ys)〜(xs '++ ys')'を持っています - コンストラクタ内の 'xs'と' ys'は現存するように数量化されているので、新しい型変数が発生します。コンパイラは 'xs〜xs 'と' ys〜ys'を推論することができません。命題平等を使用する代わりに、 'xs ++ ys = zs'という帰納的証明が必要です - ' inCatInv'も再帰的でなければならないと思います。 – user2407038
これは基本的に不可能です:タイプレベルでは、[[] ++ [x]は '[x] ++ []'と区別がつかないので、 'inCatInv'の型は本質的にあいまいです。より正確に言えば、_calls_ 'inCatInv'は' xs、ys'を選択し、 'xs ++ ys'は' InRegExp'型と同じリストです。だから、 'inCatInv'型は、' zs'を 'xs ++ ys'(呼び出し元の選択)として分割することができると期待しています。これは実際にはできません。 、AFAICS)。 – chi
あなたの補題は真実ではないようです。 'InRegexp(" ab "++" c ")(Cat" a "" bc ")'はInRegexp "ab" "a" 'を意味しません。 –