作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 User
类型,表示数据库中保存的用户。但是,在显示用户时,我只想返回这些字段的子集,因此我创建了一个不带 hash
的不同类型。创建用户时,将提供密码
而不是哈希
,因此我为此创建了另一种类型。
这显然是最糟糕的,因为我的类型之间存在大量重复。有没有更好的方法来创建多个共享某些字段的相关类型,但添加一些字段并删除其他字段?
{-# LANGUAGE DeriveGeneric #}
data User = User {
id :: String,
email :: String,
hash :: String,
institutionId :: String
} deriving (Show, Generic)
data UserPrintable = UserPrintable {
email :: String,
id :: String,
institutionId :: String
} deriving (Generic)
data UserCreatable = UserCreatable {
email :: String,
hash :: String,
institutionId :: String
} deriving (Generic)
data UserFromRequest = UserFromRequest {
email :: String,
institutionId :: String,
password :: String
} deriving (Generic)
-- UGHHHHHHHHHHH
最佳答案
在这种情况下,我认为您可以用函数替换各种 User
类型。因此,不要使用 UserFromRequest
,而是:
userFromRequest :: Email -> InstitutionId -> String -> User
请注意如何为 Email
和 InstitutionId
创建单独的类型,这将帮助您避免一堆恼人的错误。这与将带有标记字段的记录作为参数具有相同的目的,同时还添加了一些额外的静态安全性。您可以将它们实现为新类型:
newtype Email = Email String deriving (Show, Eq)
同样,我们可以将 UserPrintable
替换为 showUser
。
UserCreatable
可能有点尴尬,具体取决于您需要如何使用它。如果您对它所做的只是将其作为参数并创建数据库行,那么您可以以相同的方式将其重构为函数。但如果您确实需要该类型来处理很多事情,那么这不是一个好的解决方案。
在第二种情况下,您有几个不错的选择。一种方法是将 id
设为 Maybe
并每次检查它。更好的方法是创建一个泛型类型 WithId a
,它只向任何内容添加一个 id
字段:
data WithId a = { id :: DatabaseId, content :: a }
然后有一个 no id
的 User
类型,并让您的数据库函数与 WithId User
一起使用。
关于haskell - 如何在 haskell 中创建几种相关的数据类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27553133/
我是一名优秀的程序员,十分优秀!