我最近一直在玩MySQL-Simple。试图为该库提供一些全面的例子。我想将ID与我试图存储的实际记录分开。
要为此Entity数据类型实现QueryResults的错误情况,我需要此数据类型实际使用的字段数量。因此我引入了Arity
类型类(很容易出错,特别是在数据发生变化时)。我也在这里使用undefined
来调用arity
方法的正确实例。
我在几个例子中看到过这样的事情,但我对undefined
在这里使用感到不安。有更好的方法吗?
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE BangPatterns #-}
module Main where
import Database.MySQL.Simple
import Database.MySQL.Simple.QueryResults
import Database.MySQL.Simple.QueryParams
import Database.MySQL.Simple.Result
import Database.MySQL.Simple.Param
connectInfo :: ConnectInfo
connectInfo = defaultConnectInfo { connectUser = "dbuser" }
data Person = Person { personName :: String
, personAge :: Int
} deriving Show
class Arity a where
arity :: a -> Int
instance Arity Person where
arity _ = 2
instance QueryResults Person where
convertResults [fname, fage] [vname, vage] =
Person name age
where
!name = convert fname vname
!age = convert fage vage
convertResults fs vs = convertError fs vs 2
instance QueryParams Person where
renderParams (Person name age) = [render name, render age]
data Entity a = Entity Int a
instance (Arity a, QueryResults a) => QueryResults (Entity a) where
convertResults (fid:fs) (vid:vs) =
Entity id value
where
!id = convert fid vid
!value = convertResults fs vs
convertResults fs vs =
convertError fs vs (1 + arity (undefined :: Person))
亲切的问候,raichoo
答案 0 :(得分:7)
如果arity
仅取决于a
的选择,即其类型,则应使用基本上为()
且带有幻像类型标记的Proxy:< / p>
class Arity a where
arity :: proxy a -> Int
这样,Arity
的实例不会试图查看传递的值,客户也不需要传递底部:
instance Arity Person where
arity _ = 2
convertResults fs vs =
convertError fs vs (1 + arity (Proxy :: Proxy Person))
答案 1 :(得分:5)
我认为没关系。如果您想要非undefined
替代方案,可以使用代理幻像类型:
data Proxy a = Proxy
class Arity a where
arity :: Proxy a -> Int
instance Arity Person where
arity _ = 2
convertResults fs vs =
convertError fs vs (1 + arity (Proxy :: Proxy Person))