我有一堆复杂的类型级别函数可以评估为:
(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}}
我在上面提到的一般推论。
答案 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 :: Bool
或True
,遗憾的是,在类型级别,这不是一个简单的请求,因为False
也有Any
种类。 Bool
来自constraints
包。这是一种说法约束:-
意味着约束(a,b)
的方式。这完全如何表达您的请求 - 您需要一个证据,即两个说给定If c a b
和c x
成立,c y
也将成立强>
填写该函数的主体实际上是非常少的代码:
c (If b x y)