[英]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]
; 他们是等价的。 (巧合的是,对于字符串而不是向量使用链表的低效率是Text
和ByteString
存在的原因。)
您仍然需要转换以使其成为String
,但使用这种方法,除了人们阅读您的代码的语义提示之外, Username
和Text
类型之间没有区别。
如果您想要与String
转换,我对这些语言扩展不太熟悉,但它们看起来可以解决问题,只要您还使用type
别名而不是newtype
定义。
我认为这违背了目的。 理想情况下,您应该只将其打包到输入站点(例如,在您的 Web api 中,通常使用FromJSON
或FromHTTPApiData
类的东西隐式)并仅在使用前将其解包(例如,在查询另一个 Web api 时,通过ToJSON
隐式地,或在查询db,希望再次隐含地使用某种机制,允许您“直接”将Username
存储在您的数据库中 - 例如EntityField
用于持久性)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.