繁体   English   中英

检索通用SOP中的记录功能

[英]Retrieving record function in generic SOP

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示例,但它没有使用记录功能。

将会了解如何获取记录函数的指针(可能是HList类型HList '[(Rec -> Int), (Rec -> Maybe String)] ))。

该问题的补遗

关于如何使用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用于r每个类型x

一个实现是

  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 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM