Haskell中的简单求精类型

Haskell中的简单求精类型,haskell,types,domain-model,refinement-type,Haskell,Types,Domain Model,Refinement Type,从Scott Wlaschin和《域建模使功能化》一书以及Alexis King的书中,我认为域模型应该编码尽可能多的关于域的信息,以便“使非法状态不可表示”,并获得强有力的保证,使我能够编写完整的域逻辑函数 在基本的企业应用程序中,我们有许多基本的域名类型,如街道名称、公司名称、城市等。为了以一种防止以后出现大多数错误的形式来表示它们,我想使用一种允许 限制最大和最小字符数 指定可使用的字符子集 添加额外的约束,如无前导或尾随空格 我可以想出两种实现此类类型的方法:作为带有智能构造函数和隐

从Scott Wlaschin和《域建模使功能化》一书以及Alexis King的书中,我认为域模型应该编码尽可能多的关于域的信息,以便“使非法状态不可表示”,并获得强有力的保证,使我能够编写完整的域逻辑函数

在基本的企业应用程序中,我们有许多基本的域名类型,如街道名称、公司名称、城市等。为了以一种防止以后出现大多数错误的形式来表示它们,我想使用一种允许

  • 限制最大和最小字符数
  • 指定可使用的字符子集
  • 添加额外的约束,如无前导或尾随空格
我可以想出两种实现此类类型的方法:作为带有智能构造函数和隐藏数据构造函数的自定义抽象数据类型,或者通过某种类型级机制(我模糊地阅读了有关细化类型的内容?此类类型可以通过一些较新的语言扩展来表示吗?通过LiquidHaskell?)。哪一个是明智的选择?哪种方法最容易与在常规
文本上操作的所有函数一起工作,我如何最容易地组合相同优化类型的两个或多个值,并映射到它们上,等等


理想情况下,应该有一个库来帮助我创建这样的自定义类型。有吗?

在Alexis King的博客之后,我想说一个合适的解决方案如下。当然,其他解决方案也是可行的

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 -}

导入控制.Monad(>=>)
newtype StreetName=StreetName{getStreetName::String}
--组合所有验证并将其包装在新构造函数中。
asStreetName::String->可能是StreetName
asStreetName=StreetName rightNumberOfChars>=>rightCharSubset>=>noTrailingWhiteSpace
--此funcs将处理该字符串,并生成另一个已验证的字符串或不生成任何内容。
rightNumberOfChars::String->Maybe String
rightNumberOfChars={-…-}
rightCharSubset::String->Maybe String
RightChars子集s={-…-}
noTrailingWhiteSpace::String->Maybe String
noTrailingWhiteSpaces={-…-}
main=do
街道{-s现在已验证-}
Nothing->{-处理错误-}

StreetName
设为隐藏构造函数,将
asStreetName
设为智能构造函数。请记住,其他函数应在类型中使用
StreetName
而不是
String
,以确保数据得到验证。

考虑Liquid Haskell,它在两个选项之间取得了很好的平衡谢谢您的示例。我一直在思考这些问题。但我感到惊讶的是,这种模式似乎没有在Haskell应用程序中广泛使用,而且没有那么多库可以简化此类类型的定义。对于典型的Haskeller来说,它是否“太简单了”?在尝试此解决方案时,我添加了模式同义词,以便在不公开数据构造函数的情况下对值进行模式匹配。@UlrichSchuster将模式同义词用作智能构造函数实际上是一个好主意!可能在haskell生态系统中使用不足。我想知道为什么。。。我不认为它“太简单”,可能只是没有其他扩展那样提升。。。