gpt4 book ai didi

generics - 如何使用 GHC.Generics 的 selName 函数?

转载 作者:行者123 更新时间:2023-12-03 13:20:35 25 4
gpt4 key购买 nike

我正在寻找一个关于使用 Haskell GHC.Generics 包的 selName 函数的简单示例。

考虑以下记录类型:

{-# language DeriveGeneric #-}

data Person = Person {
firstName :: String
, lastName :: String
, age :: Integer
} deriving(Generic

如何使用 selName 函数来获取 firstName 选择器的名称?

最佳答案

下面的代码需要以下扩展:

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}

首先,您可以使用 GHCi 找出您的人物类型的通用表示:

λ> :kind! Rep Person ()
Rep Person () :: *
= M1
D
Main.D1Person
(M1
C
Main.C1_0Person
(M1 S Main.S1_0_0Person (K1 R [Char])
:*: (M1 S Main.S1_0_1Person (K1 R [Char])
:*: M1 S Main.S1_0_2Person (K1 R Integer))))
()

您要查找的选择器类型是 Main.S1_0_1Person .要提取它,您可以使用类型系列:
type family FirstSelector (f :: * -> *) :: *
type instance FirstSelector (M1 D x f) = FirstSelector f
type instance FirstSelector (M1 C x f) = FirstSelector f
type instance FirstSelector (a :*: b) = FirstSelector a -- Choose first selector
type instance FirstSelector (M1 S s f) = s
-- Note: this doesn't support types with multiple constructors.
-- You'll get a type error in that case.

我们需要一种方法来传递 Person输入我们的函数,它获取第一个选择器的名称。我们可以使用 Proxy type 来实现这一点,它只有一个构造函数,但用类型“标记”:(您也可以使用参数 undefined :: Person 并忽略它,但这样可以保证您只能忽略它)。
data Proxy a = Proxy -- also provided by the `tagged` hackage package

现在, selName的类型是 selName :: t s (f :: * -> *) a -> [Char] ,所以你需要一个匹配模式 t s (f :: * -> *) a 的类型使用该功能。我们使用相同的技巧创建一个 SelectorProxy它只有一个构造函数,但具有所需的形式:
data SelectorProxy s (f :: * -> *) a = SelectorProxy
type SelectorProxy' s = SelectorProxy s Proxy ()

最后,我们准备编写获取选择器名称的函数:
firstSelectorName :: forall a. (Generic a, Selector (FirstSelector (Rep a))) => Proxy a -> String
firstSelectorName Proxy = selName (SelectorProxy :: SelectorProxy' (FirstSelector (Rep a)))

如果你在 GHCi 中加载它,你可以看到它的工作原理:
λ> firstSelectorName (Proxy :: Proxy Person)
"firstName"

关于generics - 如何使用 GHC.Generics 的 selName 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24474581/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com