我知道如何以以下方式列出构造函数名称:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module Generics where
import Data.Proxy
import GHC.Generics
class Names' f where
names' :: Proxy f -> [String]
instance (Names' f) => Names' (M1 D t f) where
names' _ = names' (Proxy :: Proxy f)
instance (Names' f, Names' g) => Names' (f :+: g) where
names' _ = (names' (Proxy :: Proxy f) ++ (names' (Proxy :: Proxy g)))
instance (Constructor c) => Names' (C1 c f) where
names' _ = [conName (undefined :: C1 c f g)]
data Test = Foo | Bar Int | Baz { x :: Int } deriving (Generic)
main :: IO ()
main = do
print $ names' (Proxy :: Proxy (Rep Test))
--> ["Foo", "Bar", "Baz"]
但是在那种情况下,我们需要一个Proxy (Rep Test)
。如何在给定条件下做同样的事情Proxy Test
?
我找到了一个如何获取记录的第一个选择器的示例,但无法弄清楚如何解决我的问题。请帮忙。
简单:
{-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-}
names :: forall t. (Generic t, Names' (Rep t)) => Proxy t -> [String]
names _ = names' (Proxy :: Proxy (Rep t))
之所以有效,是因为Proxy
s是无关紧要的:只要您可以命名类型,就可以Proxy
为其构建a 。(旁注:除非您使用的是GHC <8,否则您可能应该使用AllowAmbiguousTypes
和TypeApplications
扩展名Proxy
。在GHC> = 8上,您唯一需要Proxy
的东西-诸如此类的情况是在更高等级的环境中。)
您可能还会说
{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, UndecidableInstances #-}
class (Generic t, Names' (Rep t)) => Names t where
names :: Proxy t -> [String]
instance (Generic t, Names' (Rep t)) => Names t where
names _ = names' (Proxy :: Proxy (Rep t))
为了得到一个很好的约束代名词Names t
了(Generic t, Names' (Rep t))
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句