我正在使用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
的实例,但我无法弄清楚如何准确地说出这一点。
我应该在这个实例的上下文中写什么才能使它工作?
答案 0 :(得分:3)
首先,您需要为单例列表提供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