结合约束条件?

Fut*_*iti 2 haskell constraints combinators

我正在寻找一种方法来组合两个(或多个)约束,这样就Combine c1 c2 a意味着c1 ac2 a,反之亦然。当约束用作输入时,这可能很有用:

data HList constraint where
  Empty :: HList constraint
  (:*:) :: constraint a => a -> HList constraint -> HList constraint
Run Code Online (Sandbox Code Playgroud)

其中shownegate可以应用于 hlist 类型的元素HList (Combine Show Num)

有了这些要求,type Combine c1 c2 a = (c1 a, c2 a)就不行了,因为类型同义词必须饱和。我也尝试声明Combine为一个类,但不能暗示这一点(Combine c1 c2 a) => c1 ac2 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)

我想知道这是否真的可能,或者有什么好的解决方法。

HTN*_*TNW 7

Combine c1 c2 a暗示c1 ac2 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)