从Scott的博客帖子和Book的“域建模使功能”和Alexis King的帖子中,我认为域模型应该编码尽可能多的域信息,以便“使非法状态无法表示”,并获得强大的保证,使我能够编写全面的域逻辑函数。
在基本的企业应用程序中,我们有许多基本的域类型,如街道名称、公司名称、城市等等。若要将它们表示为防止以后出现大多数错误的形式,我希望使用允许我使用的类型。
我可以想出两种实现这类类型的方法:使用智能构造函数和隐藏数据构造函数的自定义抽象数据类型,或者通过某种类型级别的机器(我模糊地读到了细化类型?这些类型可以通过一些较新的语言扩展来表示吗?通过LiquidHaskell?)哪一条路是明智的?哪种方法最容易与在常规Text上操作的所有函数一起工作,我如何才能最容易地组合两个或多个相同精化类型的值,并对它们进行映射等等?
理想情况下,应该有一个库来帮助我创建这样的自定义类型。在那里吗?
发布于 2020-07-09 12:44:03
在Alexis的博客之后,我想说一个合适的解决方案如下所示。当然,其他解决方案也是可行的。
import Control.Monad (>=>)
newtype StreetName = StreetName {getStreetName :: String}
-- compose all validations and wrap them in new constructor.
asStreetName :: String -> Maybe StreetName
asStreetName = StreetName <$> rightNumberOfChars >=> rightCharSubset >=> noTrailingWhiteSpace
-- This funcs will process the string, and produce another validated string or nothing.
rightNumberOfChars :: String -> Maybe String
rightNumberOfChars s = {- ... -}
rightCharSubset :: String -> Maybe String
rightCharSubset s = {- ... -}
noTrailingWhiteSpace :: String -> Maybe String
noTrailingWhiteSpaces = {- ... -}
main = do
street <- readStreetAsString
case asStreetName street of
Just s -> {- s is now validated -}
Nothing -> {- handle the error -}让StreetName成为隐藏的构造函数,就像使用asStreetName作为智能构造函数一样。请记住,其他函数应该在类型中使用StreetName而不是String,以确保数据得到验证。
https://stackoverflow.com/questions/62783722
复制相似问题