从参数约束推断类型族的约束

时间:2017-02-20 15:23:01

标签: haskell constraints typeclass type-families

我有一堆复杂的类型级别函数可以评估为:

(If (EqNat n 2)
  1
  (If (EqNat n 1)
    2
    (If (EqNat n 0) 3 0)))

现在很明显,在这种情况下,这个表达式是KnownNat。更多 通常我们可以说:

forall (c :: * -> Constraint) (p :: Bool) a b .
(c a, c b) => c (If p a b)

有没有办法教GHC推断这个?

编辑:@chi指出,在某些情况下,这可以用GADT解决,但是我的 特殊情况就是这个:

module M1 (C(..)) where

type familiy NestedIfs (n :: Nat) :: Nat
type NestedIfs n = <<complex nested ifs like the above that evals to literals>>

class C a (n :: Nat) where
  f :: KnownNat n => a -> NestedIfs n -> Bool

然后

module M2 () where
import M1

instance C Int n where
    f = ...require that KnownNat (NestedIfs n)...
NestedIfs无法访问

M2,但GHC应该可以访问forall n . KnownNat n => KnownNat (NestedIfs n) 从中推断{{1}} 我在上面提到的一般推论。

1 个答案:

答案 0 :(得分:4)

这个问题并不难,但是不合适。您期望获得c (If p a b) :: Constraint类型的价值是多少?你可能想问的是,如何填写这个

的正文
bisect :: forall b c x y. SingI b => Proxy b -> (c x, c y) :- c (If b x y)

此处,正如评论中所述,我强迫c成为单身人士,以便我可以Either (c :~: True) (c :~: False)(您可以将SingI约束视为执行{{1} }}必须是c :: BoolTrue,遗憾的是,在类型级别,这不是一个简单的请求,因为False也有Any种类。 Bool来自constraints包。这是一种说法约束:-意味着约束(a,b)的方式。这完全如何表达您的请求 - 您需要一个证据,即两个说给定If c a bc x成立,c y也将成立

填写该函数的主体实际上是非常少的代码:

c (If b x y)