如何在haskell中创建几个相关的数据类型?
我有一个如何在haskell中创建几个相关的数据类型?,haskell,types,Haskell,Types,我有一个User类型,它表示保存在数据库中的用户。但是,在显示用户时,我只想返回这些字段的一个子集,因此我创建了一个不同的类型,没有散列。在创建用户时,将提供一个密码,而不是散列,因此我为此创建了另一个类型 这显然是最糟糕的,因为我的类型之间有大量重复。有没有更好的方法来创建几个相关类型,这些类型共享一些字段,但添加一些字段并删除其他字段 {-# LANGUAGE DeriveGeneric #} data User = User { id :: String, email :: St
User
类型,它表示保存在数据库中的用户。但是,在显示用户时,我只想返回这些字段的一个子集,因此我创建了一个不同的类型,没有散列。在创建用户时,将提供一个密码
,而不是散列
,因此我为此创建了另一个类型
这显然是最糟糕的,因为我的类型之间有大量重复。有没有更好的方法来创建几个相关类型,这些类型共享一些字段,但添加一些字段并删除其他字段
{-# 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
在这种情况下,我认为可以用函数替换各种用户
类型。因此,不要使用UserFromRequest
,而是:
userFromRequest :: Email -> InstitutionId -> String -> User
请注意,您还可以为电子邮件
和机构ID
创建单独的类型,这将帮助您避免一系列恼人的错误。这与将带有标签字段的记录作为参数的目的相同,同时还增加了一点额外的静态安全性。您可以将这些实现为新类型:
newtype Email = Email String deriving (Show, Eq)
类似地,我们可以将UserPrintable
替换为showUser
usercreateable
可能有点麻烦,但这取决于您需要如何使用它。如果您所做的只是将其作为参数并创建一个数据库行,那么您可以用同样的方法将其重构为函数。但是如果你真的需要一堆东西的类型,这不是一个好的解决方案
在第二种情况下,您有几个不错的选择。一种方法是只需将id
aMaybe
,并每次检查它。更好的方法是创建一个id为A
的泛型类型,它只向任何内容添加一个id
字段:
data WithId a = { id :: DatabaseId, content :: a }
然后让一个用户
类型没有id
,让您的数据库功能与一个有id的用户
一起工作,为什么您需要用户可打印?只需创建一个showPrintable::User->String
函数。我怀疑您试图解决错误的问题。你想达到什么目标?如果您只是对不同情况下的字段子集感兴趣,那么只需传递整个类型。也许您需要将UserFromRequest替换为一个根据密码计算哈希的函数。顺便说一句,你有没有考虑过盐会去哪里?