寻找一种更好的方法来编写将类型构造函数作为参数的函数

时间:2019-03-14 23:00:44

标签: haskell servant

我有一个Haskell仆人申请。我想从文件中读取并使用文件内容填充数据库。我有这个

userList :: IO [User]
productList :: IO [Product]

data User = User { age :: Int, fname :: String, lname :: String }
data Product = Product { title :: String, description :: String }
data Item = UserI User | ProductI Product

listUsers :: Handler [Entity User]
listProducts :: Handler [Entity Product]

hydrateUserDB :: Handler [Entity User]
hydrateUserDB = do
    items <- liftIO userList
    let list = fmap User items
    traverse_ createUser list
    listUsers

hydrateProductDB :: Handler [Entity Product]
hydrateProductDB = do
    items <- liftIO productList
    let list = fmap Product items
    traverse_ createProduct list
    listProducts

现在,我想要一个可以采用User或Product并产生与上述相似结果的函数。 像这样:

hydrateDB :: Handler [Entity a]
hydrateDB =
    \alist con createItem listItems -> do
    items <- liftIO alist
    let list = fmap con items
    traverse_ createItem list
    listItems

1 个答案:

答案 0 :(得分:4)

这可能是类型类的一个好用法。将不同版本的东西放在一个类中。设计可能会得到改进,但这是第一步:

class DBItem a where
    itemList :: IO [a]
    createItem :: a -> Handler ()
    listItems :: Handler [Entity a]

instance DBItems User where
    itemList = userList
    createItem = ...
    listItems = listUsers

instance DBItems Product where
    itemList = productList
    ...

hydrateDB :: (DBItem a) => Handler [Entity a]
hydrateDB = do
    items <- liftIO itemList
    traverse_ createItem items
    listItems

(我进行了一些更改以使类型有意义,但您明白了)