我无法composite在我的全局 Stack 设置上安装相关的东西,但以下内容应该仍然有效(我只是复制粘贴了相关定义)。也就是说,我认为基于类型的简单类型类调度在这里更简单(因为约束很重要)。启用所有正确的扩展 [1],您只需要:
class Tuplify a where
tuplify :: a -> [(String, String)]
instance Tuplify (Rec Identity '[]) where
tuplify RNil = []
instance (Show t, KnownSymbol s, Tuplify (Rec Identity rs)) =>
Tuplify (Rec Identity (s :-> t ': rs)) where
tuplify (v :*: rs) = (symbolVal (Proxy :: Proxy s), show v) : tuplify rs
然后,在 GHCi 中:
ghci> tuplify ab
[("a","\"A\""),("b","1")]
如果您真的想尝试具体化约束方法,则必须首先为您想要的特定约束声明一个类型类和实例:
class ShowField a where
showField :: a -> (String, String)
instance (KnownSymbol s, Show a) => ShowField (Identity (s :-> a)) where
showField (Identity (Val v)) = (symbolVal (Proxy :: Proxy s), show v)
然后它变得更易于使用reifyConstraintsand rmap:
tuplify' :: RecAll Identity rs ShowField => Rec Identity rs -> [(String, String)]
tuplify' xs = recordToList
. rmap (\(Vinyl.Compose (Dict x)) -> Vinyl.Const $ showField x)
$ reifyConstraint (Proxy :: Proxy ShowField) xs
我想类似reifyDicts的事情可能与.ValuesAllHaveAllHaveShowField
[1] extensions needed for first example
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}