2017-08-03 54 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可以使所有這些更容易,因爲類型,種類和約束(?)更多地處於同一水平上? –