我正在编写一些mysql简单的数据库代码,我正在使我的数据类型成为QueryResults类型类的成员,以便轻松取消它们。
但我最终会遇到很多功能:
data FullName {
first_name :: String,
middle_name :: String,
last_name :: String
} deriving Show
newtype UID = UID Integer deriving Show
go :: [(String, String)] -> Maybe FullName
go fvs = do
first <- lookup "first_name" fvs
middle <- lookup "middle_name" fvs
last <- lookup "last_name" fvs
return $ FullName first middle last
go :: [(String, String)] -> Maybe UID
go fvs = do
uid <- lookup "uid" fvs
return $ UID (read uid)
其中lookup只返回(可能是a)。其中一些数据类型中包含十几列,因此这很乏味。
所以有很多这样的数据类型,我希望能够编写一个我会这样调用的函数:
go RealName ["first_name","middle_name","last_name"] fvs
go UID ["uid"] fvs
但是我不知道这种事情应该是什么类型,或者我将如何去做。也许这甚至不可能。
答案 0 :(得分:3)
使用Template Haskell,我怀疑你最终会得到这样的代码:
makeGo ''FullName
扩展为
goFullName :: [(String, String)] -> Maybe FullName
goFullName fvs = do
first <- lookup "first_name" fvs
middle <- lookup "middle_name" fvs
last <- lookup "last_name" fvs
return $ FullName first middle last
撇开:如果你import Control.Applicative
,goFullName
可以写得更简洁,就像这样:
goFullName :: [(String, String)] -> Maybe FullName
goFullName fvs
= FullName <$> lookup "first_name" fvs
<*> lookup "middle_name" fvs
<*> lookup "last_name" fvs
答案 1 :(得分:2)
我会把这个函数写成
import Control.Applicative
go :: [(String, String)] -> Maybe FullName
go fvs = FullName <$> l "first_name" <*> l "middle_name" <*> l "last_name"
where l field = lookup field fvs
答案 2 :(得分:0)
如果您的目标是最终使用QueryResults
个实例,那么为什么不执行以下操作:
{-# LANGUAGE GeneralizedNewtypeDeriving,OverloadedStrings #-}
Module Main where
import Database.MySQL.Simple
import Database.MySQL.Simple.QueryResults
import Database.MySQL.Simple.Result
import Database.MySQL.Simple.Param
data FullName =
FullName {
first_name :: String
, middle_name :: String
, last_name :: String
} deriving Show
newtype UID = UID Integer deriving (Show,Param)
instance QueryResults FullName where
convertResults fs@[_,_,_] vs@[_,_,_] = FullName first middle last
where [first,middle,last] = zipWith convert fs vs
convertResults fs vs = convertError fs vs 3
instance QueryResults UID where
convertResults fs@[fuid] vs@[vuid] = UID (convert fuid vuid)
convertResults fs vs = convertError fs vs 1
uidToFullName :: UID -> IO FullName
uidToFullName (UID uid) =
do conn <- connect defaultConnectInfo
[fn] <- query conn
"SELECT first_name,middle_name,last_name FROM user WHERE uid = ?" [uid]
return fn
示例会话:
λ> :load Main.sh
λ> uidToFullName (UID 23)
FullName {first_name = "John", middle_name = "Horatio", last_name = "Smith"}
以下是随附的SQL:
CREATE TABLE user (
uid Integer PRIMARY KEY,
email Text,
first_name Text,
middle_name Text,
last_name Text
);
INSERT INTO user VALUES (23,'john.horation@smith.com','John','Horatio','Smith');