Fut*_*iti 2 haskell constraints combinators
我正在寻找一种方法来组合两个(或多个)约束,这样就Combine c1 c2 a意味着c1 a和c2 a,反之亦然。当约束用作输入时,这可能很有用:
data HList constraint where
Empty :: HList constraint
(:*:) :: constraint a => a -> HList constraint -> HList constraint
Run Code Online (Sandbox Code Playgroud)
其中show和negate可以应用于 hlist 类型的元素HList (Combine Show Num)。
有了这些要求,type Combine c1 c2 a = (c1 a, c2 a)就不行了,因为类型同义词必须饱和。我也尝试声明Combine为一个类,但不能暗示这一点(Combine c1 c2 a) => c1 a或c2 a:
class (c1 a, c2 a) => Combine c1 c2 a
instance (c1 a, c2 a) => Combine c1 c2 a
instance Combine c1 c2 a => c1 a -- error: Illegal head of an instance declaration
instance Combine c1 c2 a => c2 a -- error: Illegal head of an instance declaration
Run Code Online (Sandbox Code Playgroud)
我想知道这是否真的可能,或者有什么好的解决方法。
Combine c1 c2 a暗示c1 a并c2 a已包含在声明中的事实
class (c1 a, c2 a) => Combine c1 c2 a
Run Code Online (Sandbox Code Playgroud)
这就是超类的工作原理!您以前肯定见过这个功能。
-- Ord is declared "class Eq a => Ord a", therefore this works
eqOrd :: Ord a => a -> a -> Bool
eqOrd = (==) -- want Eq a, have Ord a, superclass constraint says this is enough
Run Code Online (Sandbox Code Playgroud)
所以你Combine想做的一切都可以通过简单的编写来完成
class (c1 a, c2 a) => Combine c1 c2 a
instance (c1 a, c2 a) => Combine c1 c2 a
Run Code Online (Sandbox Code Playgroud)
例如以下类型检查
unzipCon :: HList (Combine c1 c2) -> (HList c1, HList c2)
unzipCon Empty = (Empty, Empty)
unzipCon (x :*: xs) = (x :*: xs1, x :*: xs2)
where (xs1, xs2) = unzipCon xs
Run Code Online (Sandbox Code Playgroud)