我知道如何通过以下方式列出构造函数名称:
{-# 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
做同样的事情?
我发现了一个example如何获取记录的第一个选择器,但不知道如何解决我的问题。请帮忙。
答案 0 :(得分:2)
简单:
{-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-}
names :: forall t. (Generic t, Names' (Rep t)) => Proxy t -> [String]
names _ = names' (Proxy :: Proxy (Rep t))
之所以起作用,是因为Proxy
是无关紧要的:只要您可以命名类型,就可以为其构建Proxy
。 (旁注:除非您使用的是GHC <8,否则您应该在AllowAmbiguousTypes
上使用TypeApplications
和Proxy
扩展名。在GHC> = 8上,您唯一需要{{ 1}}之类的东西是在较高等级的环境中。)
您可能还会说
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
。
答案 1 :(得分:1)
您可以使用Data.Data。
jQuery(document).ready(function() {
// An array of dates
var eventDates = {};
eventDates[ new Date( '12/08/2018' )] = new Date( '12/08/2018' );
eventDates[ new Date( '12/06/2014' )] = new Date( '12/06/2014' );
eventDates[ new Date( '12/20/2014' )] = new Date( '12/20/2014' );
eventDates[ new Date( '12/25/2014' )] = new Date( '12/25/2014' );
// datepicker
jQuery('#datepicker').datepicker({
beforeShowDay: function( date ) {
var highlight = eventDates[date];
if( highlight ) {
return [true, "event", highlight];
} else {
return [true, '', ''];
}
}
});
});
现在,您可以使用{-# language DerivingDataTypeable #-}
import Data.Data
import Data.Typeable
data Test = ... deriving (Data, Typeable)
来获取代表您的ADT的类型dataTypeOf
的值(例如DataType
)。
然后dataTypeOf (undefined :: Test)
将为您提供dataTypeConstrs
(构造函数)的列表。
然后在每个Constr
上打印名称。