在Haskell中使用泛型列出构造函数名称

Xafizoff

我知道如何以以下方式列出构造函数名称:

{-# 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))

之所以有效,是因为Proxys是无关紧要的:只要您可以命名类型,就可以Proxy为其构建a (旁注:除非您使用的是GHC <8,否则您可能应该使用AllowAmbiguousTypesTypeApplications扩展名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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章