haskell - 我可以让 GHC 推断出超过 GADT 模式匹配的约束吗?

标签 haskell ghc type-inference type-level-computation

我想让 GHC 推断出超过 GADT 模式匹配的约束。例如,假设我有两个表达式,每个表达式都有一个推断约束:

f :: _ => a
g :: _ => a
(在我的用例中,这些推断的约束可能很大,因此手工写出它们是不可行的。)
假设我想使用 fg取决于 bool 条件。天真地,我可以进行如下操作:
h1 :: _ => Bool -> a
h1 c = if c then f else g
假设我将推断的约束称为 f ct_fg ct_g ,则 GHC 将推断出约束 ( ct_f, ct_g )对于 h1 .
问题是这是一个过于严格的类型:如果 bool 值是 True我不需要 ct_g ,反之,如果它是 False我不需要 ct_f .所以我尝试使用标准机制来启用这样的依赖约束:
data SBool (c :: Bool) where
  SFalse :: SBool False
  STrue  :: SBool True

h2 :: _ => SBool bool -> a
h2 = \case
  STrue  -> f
  SFalse -> g
然而这不起作用,因为 GHC 的部分类型签名算法拒绝 float 约束超过 GADT 模式匹配。相反,我可以尝试明确地告诉 GHC 该怎么做:
ifC :: forall ct_t ct_f bool x. SBool bool -> ( ct_t => x ) -> ( ct_f => x ) -> ( If bool ct_t ct_f => x )
ifC STrue  a _ = a
ifC SFalse _ b = b

h3 :: _ => SBool bool -> a
h3 c = ifC c f g
这种方法也失败了,这一次是因为 GHC 认为 ifC 的类型签名模棱两可,即 GHC 需要用户显式传递约束,例如
h4 c = ifC @ct_f @ct_g c f g
不幸的是,我无法明确传递这些约束:我要求 GHC 推断它们,并且无法引用它们。例如,可以尝试将它们纳入范围,如下所示:
h5 :: _ => SBool bool -> a
h5 c = 
  let
    f :: _ct_f => a
    f' = f
    g :: _ct_g => a
    g' = g
  in
    if_C @_ct_f @_ct_g c f' g'
但这行不通,因为 GHC 不支持命名通配符代替额外的约束(即使支持,它们也不会正确地作用域)。
是否有另一种方法可以让 GHC 推断:
h :: ( If bool ct_f ct_g ) => a

最佳答案

我用 ImpredicativeTypes 稍微改进了代码.

type family GetBool a where
  GetBool (SBool True) = True 
  GetBool (SBool False) = False

data TF (a :: Constraint) x = TF x

class SIf a pt pf x where
  ifC' :: a -> TF pt x -> TF pf x -> (If (GetBool a) pt pf => x)

instance ((t => x) ~ (f => x)) => SIf (SBool True) t f x where
  ifC' _ (TF t) _ = t

instance ((t => x) ~ (f => x)) => SIf (SBool False) t f x where
  ifC' _ _ (TF f) = f

h3' :: _ => SBool bool -> a
h3' c = ifC' c f g

它可以给它Num a实例。
*Main> :t h3' 3
h3' 3
  :: (If (GetBool (SBool bool)) pt pf, SIf (SBool bool) pt pf a,
      Num (SBool bool)) =>
     a
let x = h3' f现在也可以,但并不完美。我想我们做的是黑魔法...

关于haskell - 我可以让 GHC 推断出超过 GADT 模式匹配的约束吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65338390/

相关文章:

haskell - Haskell 中的通用默认值

java - 为什么从 try-catch block 内部返回 CompletableFuture.completedFuture(...) (似乎)会导致此错误?

c# - 在 C# 中,使用 var 的推断变量在内存和生命周期方面的行为如何?

emacs 中的 Haskell 加载模块问题

string - Haskell 写入 '\n' 而不是换行符

haskell - 让 Cabal 使用 GHC 6.12.1

kotlin - Lambda参数类型的类型推断

Haskell:在类型类中定义变量

haskell - monad 运算符名称的继承

haskell - 我是否应该使用 GHC Haskell 扩展?