代码之家  ›  专栏  ›  技术社区  ›  Alexey Vagarenko

如何为递归单例类型定义NFData实例?

  •  3
  • Alexey Vagarenko  · 技术社区  · 9 年前

    我正在使用 singletons 图书馆我有此数据类型:

    import Control.DeepSeq
    import Data.Singletons.Prelude
    import Data.Singletons.TH
    
    data T =
          A
        | B [T]
    
    genSingletons [''T]
    

    我想要生成的单例类型 ST 成为…的实例 NFData . 如果键入 T 不会是递归的。 我试着这样写:

    instance NFData (ST a) where
        rnf SA = ()
        rnf (SB (x `SCons` xs)) = rnf x `seq` rnf xs
    

    但这在最后一行失败,并显示消息:

    Could not deduce (NFData (Sing n1)) arising from a use of `rnf'
    from the context (a ~ 'B n)
      bound by a pattern with constructor
                 SB :: forall (z_azEs :: T) (n_azEt :: [T]).
                       (z_azEs ~ 'B n_azEt) =>
                       Sing n_azEt -> Sing z_azEs,
               in an equation for `rnf'
    or from (n ~ (n0 : n1))
      bound by a pattern with constructor
                 SCons :: forall (a0 :: BOX) (z0 :: [a0]) (n0 :: a0) (n1 :: [a0]).
                          (z0 ~ (n0 : n1)) =>
                          Sing n0 -> Sing n1 -> Sing z0,
               in an equation for `rnf'
    In the second argument of `seq', namely `rnf xs'
    In the expression: rnf x `seq` rnf xs
    In an equation for `rnf':
        rnf (SB (x `SCons` xs)) = rnf x `seq` rnf xs
    

    我知道GHC想要 x xs 在模式中 SB (x ``SCons`` xs)) 成为…的实例 NFData公司 ,但我很难弄清楚如何确切地说出这一点。 我应该在这个实例的上下文中写些什么来使其工作?

    1 回复  |  直到 9 年前
        1
  •  3
  •   András Kovács    9 年前

    首先,您需要提供 NFData 单例列表的实例。

    instance NFData (SList '[]) where
      rnf SNil = ()
    
    instance (NFData (Sing x), NFData (SList xs)) => NFData (SList (x ': xs)) where
      rnf (SCons x xs) = rnf x `seq` rnf xs
    

    请注意,您不能在单个实例中解决此问题,因为这样就不能提供递归 NFData公司 约束条件:

    instance NFData (SList xs) where
      rnf SNil = ()
      rnf (SCons x xs) = ? -- no way to know if NFData (Sing x)
    

    类似地,您必须为 T 案例:

    instance NFData (ST A) where
      rnf SA = ()
    
    instance NFData (SList xs) => NFData (ST (B xs)) where
      rnf (SB xs) = rnf xs