我正在處理Haskell中的依賴類型程序的一個示例,我想「重寫」一個在singletons庫中定義的命題相等類型a :~: b
的證據。Haskell中的依賴類型編程的更多問題
更具體地說,我有一個數據類型來表示正則表達式成員的證據。我的麻煩是如何處理兩個正則表達式串聯的證據。在我的代碼中,我有一個名爲InRegExp xs e
的GADT,它表示xs
是使用正則表達式e
的語言。對於級聯,我有以下構造函數:
InCat :: InRegExp xs l -> InRegExp ys r ->
(zs :~: xs ++ ys) -> InRegExp zs (Cat l r)
到目前爲止,這麼好。現在,我想在兩個正則表達式的串聯來定義反轉引理成員:
inCatInv :: InRegExp (xs ++ ys) (Cat e e') -> (InRegExp xs e , InRegExp ys e')
inCatInv (InCat p p' Refl) = (p , p')
但是代碼是由GHC與以下錯誤消息拒絕:
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')
在阿格達或伊德里斯,這反轉引理類型很好。在Haskell中可以表達這樣的反轉引理嗎?完整的代碼可在以下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'類型向_caller_保證是可以的,它可以將'zs'以任何可能的方式分割爲'xs ++ ys'(調用者的選擇),這不是它真正做的(也不是它打算做什麼,AFAICS)。 – chi
你的引理看起來不正確。 'InRegexp(「ab」++「c」)(Cat「a」「bc」)'不暗示'InRegexp「ab」「a」'。 –