我如何限制黑胶唱片/复合唱片?
How can I constrain Vinyl / Composite Records?
我有一个可扩展的Vinyl / Composite记录(类似于HList,Frames...),我想生成keys/values的元组,例如
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,它有经过深思熟虑的示例和我看到的错误:
这是Composite中refying的硬件(reifyDicts
):
乙烯基也一样(reifyConstraints
):
AFAICT,问题在于 rmap
:
rmap :: (forall x. f x -> g x) -> Rec f rs -> Rec g rs
映射的 fn 已定义 forall x
,但我的 tuplify
受到约束,我认为具体化应该将约束移动到类型中(这就是 Dict
的用途) ,但是,唉,到目前为止运气不好。
我无法在我的全局 Stack 设置中安装 composite
相关内容,但以下内容应该仍然有效(我只是复制粘贴了相关定义)。也就是说,我认为基于类型的简单 type-class 调度在这里更简单(因为约束是不平凡的)。启用所有正确的扩展 [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 和实例:
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)
那么使用reifyConstraints
和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
也可能有类似的东西,尽管我希望有一个使用 ValuesAllHave
而不是 AllHave
定义的变体(这样我们就可以绕过声明 ShowField
键入 class 并在一个函数中完成所有操作)。
[1] extensions needed for first example
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
我有一个可扩展的Vinyl / Composite记录(类似于HList,Frames...),我想生成keys/values的元组,例如
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,它有经过深思熟虑的示例和我看到的错误:
这是Composite中refying的硬件(reifyDicts
):
乙烯基也一样(reifyConstraints
):
AFAICT,问题在于 rmap
:
rmap :: (forall x. f x -> g x) -> Rec f rs -> Rec g rs
映射的 fn 已定义 forall x
,但我的 tuplify
受到约束,我认为具体化应该将约束移动到类型中(这就是 Dict
的用途) ,但是,唉,到目前为止运气不好。
我无法在我的全局 Stack 设置中安装 composite
相关内容,但以下内容应该仍然有效(我只是复制粘贴了相关定义)。也就是说,我认为基于类型的简单 type-class 调度在这里更简单(因为约束是不平凡的)。启用所有正确的扩展 [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 和实例:
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)
那么使用reifyConstraints
和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
也可能有类似的东西,尽管我希望有一个使用 ValuesAllHave
而不是 AllHave
定义的变体(这样我们就可以绕过声明 ShowField
键入 class 并在一个函数中完成所有操作)。
[1] extensions needed for first example
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}