代码之家  ›  专栏  ›  技术社区  ›  nicolas

使用“proxy s”绑定类型与使用forall绑定类型

  •  2
  • nicolas  · 技术社区  · 6 年前

    在下面的例子中,我不清楚为什么 toto 会失败,而 tata 会起作用。

    对此有什么解释吗?

    {-# LANGUAGE AllowAmbiguousTypes  #-}
    {-# LANGUAGE  TypeFamilies, KindSignatures, FlexibleContexts #-}
    {-# LANGUAGE TypeApplications, FunctionalDependencies, MultiParamTypeClasses #-}
    {-# LANGUAGE ScopedTypeVariables , GADTs, MultiParamTypeClasses, RankNTypes                #-}
    {-# LANGUAGE TypeOperators, UnicodeSyntax, DataKinds              #-}
    
    import Data.Proxy
    
    data KNat where
    class ReflectNum (s :: KNat) where
    
    toto ∷ (∀ (s :: KNat). ReflectNum s ⇒ Int) → Int
    toto k = toto k
    
    tata ∷ (∀ (s :: KNat). ReflectNum s ⇒ Proxy s -> Int) → Int
    tata k = tata (\(p :: Proxy s) -> k p)
    

    误差是

    SO.hs:14:15: error:
        • Could not deduce (ReflectNum s0) arising from a use of ‘k’
          from the context: ReflectNum s
            bound by a type expected by the context:
                       forall (s :: KNat). ReflectNum s => Int
            at SO.hs:14:10-15
          The type variable ‘s0’ is ambiguous
        • In the first argument of ‘toto’, namely ‘k’
          In the expression: toto k
          In an equation for ‘toto’: toto k = toto k
       |
    14 | toto k = toto k
       |               ^
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   Alexis King    6 年前

    这是ghc_实现可见类型应用程序的已知限制。明确地, Proxy 有时仍然是必要的,以便允许参数更高级别的函数(例如 toto 函数)访问类型变量。

    有一个GHC建议,以以下形式为这个问题添加解决方案: type variable bindings in lambda-expressions . 使用建议中的语法, 托托 函数可以写为

    toto k = toto (\@s -> k @s)
    

    本地绑定 s 变量。可悲的是,这项提议还没有实施。

    同时,对于像这样的高级功能,我想您只需要使用 代理 . 对不起的。