[英]Statically analyze type with Generics
For the purpose of generically deriving instances for FromRow
-kind-of-class on simple products I would like to statically analyze a type without actually providing any concrete terms.为了在简单产品上为
FromRow
类一般派生实例,我想静态分析一个类型,而不实际提供任何具体术语。
Example:例子:
class FromRow a where
rowrep :: Proxy a -> [Maybe NativeType]
fromRow :: Statement -> IO a
data User = User
{ name :: String
, uid :: Int
, active :: Bool
} deriving (Show, Generic)
The "trick" is I need the rowrep before I fetch any data - to possibly override the defaults for some or even all columns. “技巧”是我在获取任何数据之前需要 rowrep - 可能会覆盖某些甚至所有列的默认值。 At the point in time where I want to use rowrep I don't yet have a term, thus the
Proxy
.在我想使用 rowrep 的时间点我还没有一个术语,因此
Proxy
。 Writing instances of FromRow
could get extremely tedious and error prone so I thought I'd add a default
implementation for Generic
types.编写
FromRow
实例可能会变得非常乏味且容易出错,所以我想我会为Generic
类型添加一个default
实现。 However, it seems to get the generic representation I need to provide a term of a given type ( from :: a -> Rep a
), knowledge of type itself is not enough.然而,它似乎得到了我需要提供给定类型的术语(
from :: a -> Rep a
)的通用表示,类型本身的知识是不够的。
Indeed we can see this isn't just a gimmick of the API and that Generic representations do hold values:事实上,我们可以看到这不仅仅是 API 的噱头,泛型表示确实包含值:
> from (User "foo" 1 True)
M1 {unM1 = M1 {unM1 = M1 {unM1 = K1 {unK1 = "foo"}} :*: (M1 {unM1 = K1 {unK1 = 1}} :*: M1 {unM1 = K1 {unK1 = True}})}}
Is there a way to use Generic
just to analyze the structure and type of things ie where we don't care about actual values?有没有一种方法可以使用
Generic
来分析事物的结构和类型,即我们不关心实际值的地方? Failing that, is TH going to cover this use case?如果做不到这一点,TH 会涵盖这个用例吗?
You don't need to provide a term.您无需提供术语。 You don't need a value of
Rep a
, you just need to inspect this as a type , and that can be done without ever using from
.您不需要
Rep a
的值,您只需要将其作为type进行检查,并且无需使用from
即可完成此操作。
For that matter, you also don't need Proxy
, that was always just an ugly hack to make up for a deficiency of Haskell before TypeApplications
came along.就此而言,你也不需要
Proxy
,在TypeApplications
出现之前,这总是一个丑陋的黑客来弥补 Haskell 的不足。
{-# LANGUAGE TypeFamilies, TypeApplications, AllowAmbiguousTypes
, ScopedTypeVariables, UnicodeSyntax, DefaultSignatures #-}
data NativeType = Intish | Floatish
class FromRow a where
rowrep :: [Maybe NativeType]
instance FromRow Int where
rowrep = [Just Intish]
Now, for writing generic instances we first need a helper class that does the type-level inspection of the Rep
:现在,为了编写通用实例,我们首先需要一个辅助类来对
Rep
进行类型级别的检查:
class GFromRow g where
gRowrep :: [Maybe NativeType]
instance ∀ i c f . GFromRow f => GFromRow (M1 i c f) where
gRowRep = gRowRep @f
instance ∀ i c . FromRow c => GFromRow (K1 i c) where
gRowRep = rowRep @c
... -- instances for U1 and f:*:g
Then the default implementation will be那么默认的实现将是
class FromRow a where
rowrep :: [Maybe NativeType]
default rowrep :: GFromRow (Rep a) => [Maybe NativeType]
rowrep = gRowrep
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.