gpt4 book ai didi

haskell - 如何在 haskell 中创建几种相关的数据类型?

转载 作者:行者123 更新时间:2023-12-02 13:58:38 26 4
gpt4 key购买 nike

我有一个 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

请注意如何为 EmailInstitutionId 创建单独的类型,这将帮助您避免一堆恼人的错误。这与将带有标记字段的记录作为参数具有相同的目的,同时还添加了一些额外的静态安全性。您可以将它们实现为新类型:

newtype Email = Email String deriving (Show, Eq)

同样,我们可以将 UserPrintable 替换为 showUser

然而,

UserCreatable 可能有点尴尬,具体取决于您需要如何使用它。如果您对它所做的只是将其作为参数并创建数据库行,那么您可以以相同的方式将其重构为函数。但如果您确实需要该类型来处理很多事情,那么这不是一个好的解决方案。

在第二种情况下,您有几个不错的选择。一种方法是将 id 设为 Maybe 并每次检查它。更好的方法是创建一个泛型类型 WithId a ,它只向任何内容添加一个 id 字段:

data WithId a = { id :: DatabaseId, content :: a }

然后有一个 no idUser 类型,并让您的数据库函数与 WithId User 一起使用。

关于haskell - 如何在 haskell 中创建几种相关的数据类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27553133/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com