繁体   English   中英

Haskell:将新类型视为字符串

[英]Haskell: treat newtype as String

我经常有这个简单的模式:

newtype Username = Username Text

目的当然是在操作“用户名”时提高安全性,而不是将其与其他字段混合。 然而,一直打包和拆包变得乏味。 我想知道是否有将“用户名”视为字符串(例如 AsString 或 OverloadedStrings)的技巧,还是违背了目的?

我认为你的newtype方法是一个很好的方法。 你必须问问自己,为什么你一直需要打包和拆包。 对于这样的类型,您通常应该有一个定义它的模块、一堆乏味的类型类实例和一些操作函数。 你只要把它敲出来。

{-# language GeneralizedNewtypeDeriving #-}

module MyNamespace.Username (.....) where
import Data.Hashable

newtype Username = Username Text
  deriving (Eq, Ord, Show, Hashable)

unUsername :: Username -> Text
validateForm :: Text -> Maybe Username

如果你想要适当的类型安全,你应该使用newtype 这旨在防止您隐式地来回转换以防止意外错误。

如果你只是想要一个不会妨碍你的类型别名,你应该使用 type 关键字:

type Username = Text

这意味着接受Username的函数可以接受Text而无需调用值构造函数等。实际上, String被定义为type String = [Char]因此您可以在需要字符串的任何地方提供[Char] 他们是等价的。 (巧合的是,对于字符串而不是向量使用链表的低效率是TextByteString存在的原因。)

您仍然需要转换以使其成为String ,但使用这种方法,除了人们阅读您的代码的语义提示之外, UsernameText类型之间没有区别。

如果您想要与String转换,我对这些语言扩展不太熟悉,但它们看起来可以解决问题,只要您还使用type别名而不是newtype定义。

我认为这违背了目的。 理想情况下,您应该只将其打包到输入站点(例如,在您的 Web api 中,通常使用FromJSONFromHTTPApiData类的东西隐式)并仅在使用前将其解包(例如,在查询另一个 Web api 时,通过ToJSON隐式地,或在查询db,希望再次隐含地使用某种机制,允许您“直接”将Username存储在您的数据库中 - 例如EntityField用于持久性)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM