gpt4 book ai didi

haskell - 推断两个记录中公共(public)字段的类型

转载 作者:行者123 更新时间:2023-12-02 10:43:41 26 4
gpt4 key购买 nike

如果这是一个愚蠢的问题,请耐心等待。如何键入一个接受两条记录并返回其公共(public)字段数组的通用函数?

假设我有:

type A = { name :: String, color :: String }
type B = { name :: String, address :: Address, color :: String }

myImaginaryFunction :: ???
-- should return ["name", "color"] :: Array of [name color]

我想编写一个函数,它接受ANY两种类型的记录并返回一个公共(public)字段数组。 Haskell 解决方案也可以工作。

最佳答案

要在 Haskell 中表达具有公共(public)字段的两种记录类型,您需要一个 GHC 扩展:

{-# LANGUAGE DuplicateRecordFields #-}

要内省(introspection)字段名称,您需要基于 Data 类的泛型:

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data ( Data, Typeable, DataRep(AlgRep), dataTypeRep
, dataTypeOf, constrFields)
import Data.List (intersect)
import Data.Proxy (Proxy(..), asProxyTypeOf)

这将允许您使用相同的字段名称定义两种数据类型:

data Address = Address String deriving (Typeable, Data)
data A = A { name :: String, color :: String }
deriving (Typeable, Data)
data B = B { name :: String, address :: Address, color :: String}
deriving (Typeable, Data)

然后您可以使用以下方法检索字段名称:

fieldNames :: (Data t) => Proxy t -> [String]
fieldNames t = case dataTypeRep $ dataTypeOf $ asProxyTypeOf undefined t of
AlgRep [con] -> constrFields con

并获取公共(public)字段:

commonFields :: (Data t1, Data t2) => Proxy t1 -> Proxy t2 -> [String]
commonFields t1 t2 = intersect (fieldNames t1) (fieldNames t2)

之后,以下内容将起作用:

ghci> commonFields (Proxy :: Proxy A) (Proxy :: Proxy B)
["name", "color"]
ghci>

请注意,上面 fieldNames 的实现假设只有具有单个构造函数的记录类型才会被内省(introspection)。如果您想概括它,请参阅 Data.Data 的文档。

现在,因为您是一个帮助吸血鬼,我知道您会需要类型级函数,即使您在问题中没有提到需要类型级函数!事实上,我可以看到您已经添加了一条评论,说明您对如何以某种方式返回 name | 数组感兴趣。 color 尽管 Haskell 中不存在这样的东西,即使您在问题中明确表示您期望术语级别的答案 ["name", "color"]

不过,可能有非吸血鬼也有类似的问题,也许这个答案会对他们有所帮助。

关于haskell - 推断两个记录中公共(public)字段的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48994927/

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