gpt4 book ai didi

haskell - 通用SOP中的检索记录功能

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

Sum of Products方法,如何检索记录功能?下面是记录数据类型的示例代码 (ghc 7.10.3):

{-# LANGUAGE DeriveGeneric #-}
import qualified GHC.Generics as GHC
import Generics.SOP
data Rec = Rec { frec :: Int, srec :: Maybe String}
deriving (Show, GHC.Generic)

instance Generic Rec -- empty
instance HasDatatypeInfo Rec

让我们在 ghci 提示符处查看 DataTypeInfo:

*Main> datatypeInfo (Proxy :: Proxy Rec)
ADT "Main" "Rec" (Record "Rec" (FieldInfo "frec" :* (FieldInfo "srec" :* Nil)) :* Nil)

我们看到frecsrec都是FieldInfo类型,它有一个构造函数FieldInfo,它接受fieldName 作为字符串。因此,我没有找到任何方法来获取实际函数 frec::Rec -> Intsrec::Rec -> Maybe String。我还看了show example但它不使用记录功能。

非常感谢有关如何获取记录函数的指针(可以是 HList '[(Rec -> Int), (Rec -> Maybe String)]) 类型的 HList。

问题附录

我对如何使用 user2407038 提出的方法从投影中获取函数感到困惑。因此,我想进一步补充这个问题:我们如何在 Rec 构造函数上使用 SOP 方法构建如下所示的函数 - 我们同时使用记录字段名称和这里的函数:

[ ("frec" ++) . show . frec, ("srec" ++) . show . srec] 

最佳答案

generics-sop库实现了用于处理乘积之和的通用组合器,因此您应该使用这些组合器编写这样的函数。

有一个问题 - generics-sop没有关于类型级别上的记录与构造函数的任何信息,因此您的函数仍然是部分的(除非您深入研究 GHC 泛型 Rep )。

对于这个例子,我将只使用部分函数路线。

首先,您需要此数据类型:

data (:*:) f g x = f x :*: g x deriving (Show, Eq, Ord, Functor) 

看起来它应该包含在库中,但事实并非如此(或者我找不到它)。

函数的类型为

recordSelectors :: forall t r . (Code t ~ '[ r ], Generic t, HasDatatypeInfo t) 
=> Proxy t -> Maybe (NP (FieldInfo :*: (->) t) r)

约束Code t ~ '[ r ]只是说 t 的产生式表示之和是一个单例列表(一个构造函数)。返回类型(可能)是列表中的产品 r (记录字段类型列表)其中有 FieldInfo x和一个 t -> x对于每种类型xr

一种实现是

  case datatypeInfo (Proxy :: Proxy t) of 
ADT _ _ (Record _ fields :* Nil) -> Just $
hzipWith (\nm (Fn prj) -> nm :*: (unI . prj . K . (\(Z x) -> x) . unSOP . from))
fields
projections
_ -> Nothing

这里函数确定给定的数据类型确实是一条记录,否则返回 Nothing 。如果是记录,则将记录字段和 projections 压缩在一起(由库定义),它定义了任意通用产品的投影,本质上就是 NP '[ Code Rec -> Int, Code Rec -> Maybe String ]适合您的类型。剩下的就是编写 from与每个投影一起使用以获得“真实”投影。其余的( FnunSOP 等)只是身份。

<小时/>

由于事实证明您只需要记录投影函数,没有函数名称,因此这更加简单。现在该函数不是部分的 - 任何一种构造函数类型都具有“记录投影”。

recordSelectors' :: forall t r . (Code t ~ '[ r ], Generic t) 
=> Proxy t -> NP ((->) t) r
recordSelectors' _ = hmap (\(Fn prj) -> unI . prj . K . (\(Z x) -> x) . unSOP . from)
projections

关于haskell - 通用SOP中的检索记录功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36254349/

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