2017-07-02 84 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