2017-07-02 78 views
3

我想在數據類型名稱上做一些淺印刷,但我不知道如何用Generics-SOP做到這一點。如何從SOP表示轉換後的類型獲取數據類型信息?

對於在那裏我有我的NEWTYPE的列表的情況下,我可以打印出什麼,我很容易需要:

class GTypeName f where 
    gtypeName :: g f -> String 

instance (HasDatatypeInfo a) => GTypeName (SOP I ('[ '[], '[a, [a]] ])) where 
    gtypeName _ = "(Array " ++ name ++ ")" 
    where 
     name = datatypeName $ datatypeInfo (Proxy @ a) 

正如你所看到的,我匹配名單上的種類和使用內a的數據類型信息來獲取名稱。但是我不知道如何處理這種情況,我希望得到實際的頂層構造函數名稱本身。

在GHC泛型我做了以下內容:

instance (GTypeName f) => GTypeName (D1 m f) where -- peer inside 
    gtypeName _ = gtypeName (Proxy @ f) 

-- go into the Cons constructed type 
instance {-# OVERLAPPING #-} (GTypeName f) => GTypeName (C1 ('MetaCons ":" g s) f) where 
    gtypeName _ = gtypeName (Proxy @ f) 

-- return the constructor name here 
instance (KnownSymbol n) => GTypeName (C1 ('MetaCons n g s) f) where 
    gtypeName _ = symbolVal (Proxy @ n) 

-- take the left side, as this is the result of a type product from Cons 
instance (GTypeName a) => GTypeName (a :*: b) where 
    gtypeName _ = 
    gtypeName (Proxy @ a) 

-- match on array and take it out here 
instance (GTypeName b) => GTypeName ((C1 ('MetaCons "[]" g s) f) :+: b) where 
    gtypeName _ = "(Array " ++ gtypeName (Proxy @ b) ++ ")" 

這是最終使用一個NEWTYPE和一些數據類型,像這樣:

newtype Status = Status Text 

newtype OpenRequest = OpenRequest 
    { path :: Path 
    } 

data Route req res = Route 
    { method :: Method 
    , url :: Url 
    } 

open :: Route OpenRequest Success 
open = Route {method = POST, url = Url "/api/open"} 

回答

1

你可以得到頂級的構造函數名使用泛型-sop的值如下:

constructor :: 
    forall a . 
    (Generic a, HasDatatypeInfo a) => a -> String 
constructor a = 
    hcollapse $ 
    hzipWith 
    (\ con _args -> K (constructorName con)) 
    (constructorInfo (datatypeInfo (Proxy @a))) 
    (unSOP $ from a) 

在這裏,constructorInfo ...給你一個產品包含有問題的數據類型的所有構造函數名稱。調用hzipWith然後選擇給定值a所屬的構造函數。

例子:

GHCi> constructor True 
"True" 
GHCi> constructor (Just 3) 
"Just" 
GHCi> constructor [1,2,3] 
":" 

不幸的是,它並不完全清楚,我要與列表類型做什麼,所以我不能說明如何將它與你已有的代碼合併。

+0

對不起,意識到我的標題中的問題與身體內容完全不同,但後來我發現由於我只是用數據類型調用我的方法,所以我可以用較少的解決方法逃脫。謝謝!我有我的回購在這裏我現在試圖將ExtractFields實例轉換爲SOP在這裏:https://github.com/justinwoo/godawful-purescript-codegen-demo – kakigoori