我有一個功能foo
與一系列的約束。當然,這些約束必須出現在使用foo
的函數的簽名中,所以我試圖做的是將foo
約束包含在類型同義詞FooCtx a b ... :: Constraint
中。作爲一個例子,利用fundeps綁定約束
foo :: (A a, B b, C c, ...) => a -> b -> c
bar :: (A a, B b, C c, ...) ...
bar = ... foo ...
將成爲
type FooCtx a b c ... = (A a, B b, C c, ...)
foo :: (FooCtx a b c) => a -> b -> c
bar :: (FooCtx a b c) => ...
如果所有類型的暴露這個偉大的工程。但是,我正在使用函數依賴來生成約束列表中的某些類型,並且這些類型不會出現在foo
的簽名中。例如:
class Bar a b | a -> b
foo (Bar a b, ...) => a -> a
GHC不會接受type FooCtx a = (Bar a b)
因爲b
未綁定的LHS。我也不能使用type FooCtx a b = (Bar a b)
,因爲b
不在foo
的簽名範圍內。 foo
的簽名應爲foo :: (FooCtx a ?) => a -> a
。
一個不能令人滿意的解決辦法是把制約因素之一在foo
簽名與FooCtx
帶來fundep類型中範圍:
class Bar a b | a -> b
type FooCtx a b = ...
foo (Bar a b, FooCtx a b) => a -> a
但這違背了分組的約束的目的:
在遇到這種情況之前,我認爲約束同義詞可以被盲目取代任意約束列表。我知道封裝這樣的約束的唯一方法是使用一個類,但它遭受同樣的問題:class (A a, B b, C c, ...) => FooCtx a b c
在LHS上不能有任何隱藏類型。有沒有其他方法可以完全收集所有這些限制?
「type FooCtx a b = ...'出現了什麼問題 - 這隻比'type FooCtx a = ...'長2個字符。 – user2407038 2015-03-03 04:16:56
正如我上面提到的,GHC接受你的簽名,但對於'foo'的LHS我沒用,因爲'b'不在'foo'的簽名範圍內。 – crockeea 2015-03-03 04:18:58
是否有任何理由不能使用'TypeFamilies'而不是'FunctionalDependencies'? – Cirdec 2015-03-03 04:59:14