2017-08-03 60 views
1

我有一个可扩展的乙烯基/复合记录(类似于HList,帧...),并且我想生成密钥/值的元组,如如何约束乙烯基/复合记录?

tuplify '[String :-> Whatevs, ...] :: [(String, String)] 

这是令人惊讶的硬。 original gist

Solution Gist, thanks to Alec below

type FA = "a" :-> String 
type FB = "b" :-> Int 
type AB = '[FA, FB] 

ab :: Rec Identity AB 
ab = "A" :*: 1 :*: RNil 

tuplify :: (Show a) => Rec Identity '[a] -> [(String, String)] 
tuplify = recordToList . rmap undefined -- ?????? 
-- tuplify ab = [("a", "A"), ("b", "1")] 

如果你愿意尝试什么我迄今所做的,签出gist,它具有良好的深思熟虑的例子,我看到了错误:

这里是复合(reifyDicts):

的硬件refying与同为乙烯(reifyConstraints):

AFAICT,问题是,在类似rmap

rmap :: (forall x. f x -> g x) -> Rec f rs -> Rec g rs 

的映射FN定义forall x,但我tuplify受到限制,而且我觉得物化应该移动的约束代入式(这是Dict s为因为),但是,唉,至今没有运气。

+0

你避免使用reifyNames'的'? (似乎已经为这种事情做好了准备......) – Alec

回答

2

我不能得到composite相关的东西安装在我的全局堆栈设置,但以下应该仍然工作(我只是复制粘贴相关定义)。也就是说,我认为基于类型的简单的基于类的派发在这里更简单(因为约束是非平凡的)。与所有正确的扩展名启用[1],你只需要:

​​

然后,在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) 

然后它变得更直tforward使用reifyConstraintsrmap

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,但我希望能有它定义使用ValuesAllHave,而不是仅仅AllHave(那么我们就可以绕过声明ShowField类型类,做的一个变种一切只在一个函数中)。


[1] extensions needed for first example 

{-# LANGUAGE DataKinds   #-} 
{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE GADTs    #-} 
{-# LANGUAGE RankNTypes   #-} 
{-# LANGUAGE ScopedTypeVariables #-} 
{-# LANGUAGE TypeFamilies  #-} 
{-# LANGUAGE TypeOperators  #-} 
+0

'复合材料'图书馆似乎是过分设计的,几乎没有任何好处。例如,你声明'ValuesAllHave'应该有'reifyDicts'的变体;但是如果没有声明一个额外的类来证明每个'rs'确实是一个': - >'(例如'class IsAssoc a isASasoc :: forall r。a - >(forall sv。((s: - > v)〜a)=> r) - > r') - 你的'ShowField'提供了这个证明。此外,'reifyDicts'使用'RecApplicative'来重建列表的脊柱,而不是仅仅对输入进行归纳。 '复合材料'根本没有简单的方法来执行这个(简单)操作! – user2407038

+0

@ user2407038我完全同意。我也尝试积极使用他们提供的机器,我最终提出的解决方案比我发布的解决方案长两倍,并且不那么清晰。 :/ – Alec

+0

谢谢!我是否正确地认为依赖型打字或者甚至只是TypeInType可以使所有这些更容易,因为类型,种类和约束(?)更多地处于同一水平上? –