haskell - 序列号的建设性处理
问题描述
我正在实现一个简单的协议,其中消息的序列号必须在消息之间严格递增。为了解决这个问题,我写道:
newtype SequenceNo = SequenceNo Int64
deriving (Show, Eq)
validSequence :: SequenceNo -> SequenceNo -> Bool
validSequence (SequenceNo firstS) (SequenceNo secondS) = firstS + 1 == secondS
我使用它是这样的:
applyUpdates :: ProtocolState -> UpdateMessage -> Either String ProtocolState
applyUpdates oldState upd =
if validSequence (seqNo oldState) (updSeqNo upd)
then Right (ProtocolState {seqNo=updSeqNo upd, …})
else Left "invalid sequence"
但这具有与布尔盲相同的问题isJust :: Maybe a -> Bool
。我怎样才能做得更好?
解决方案
我只想定义一个与 同构的类型Bool
,但使用更具描述性的构造函数名称。
date Validity = Valid | Invalid
然后编写一个函数,返回由参数表示的序列类型:
classifySequence :: SequenceNo -> SequenceNo -> Validity
classifySequence (SequenceNo x) (SequenceNo y) | x + 1 == y = Valid
| otherwise = Invalid
如果您Enum
为您的类型定义一个实例,那就更简单了。
newtype SequenceNo = SequenceNo Int64 deriving (Show, Read, Eq, Enum)
classifySequence :: SequenceNo -> SequenceNo -> Validity
classifySequence x y | succ x == y = Valid
| otherwise = Invalid
无论哪种方式,您都可以定义
applyUpdates :: ProtocolState -> UpdateMessage -> Either String ProtocolState
applyUpdates oldState upd =
case validSequence (seqNo oldState) (updSeqNo upd) of
Valid -> Right (ProtocolState {seqNo=updSeqNo upd, …})
Invalid -> Left "invalid sequence"
尽管您也可能会考虑显式错误类型:
data SequenceError = InvalidSequence
applyUpdates :: ProtocolState -> UpdateMessage -> Either SequenceError ProtocolState
applyUpdates oldState upd =
case validSequence (seqNo oldState) (updSeqNo upd) of
Valid -> Right (ProtocolState {seqNo=updSeqNo upd, …})
Invalid -> Left InvalidSequence
推荐阅读
- javascript - V-if 在组件道具上
- react-native - 为什么我在 windows pc 上收到 react-native command not found 错误?
- c++ - 编译 Orbiter 示例时出现 C++ 错误 - LNK2019 未解析的外部符号
- html - 为什么 bootstrap 将这些缩放的元素垂直堆叠在列中?
- c++ - C++ 编译器为两个变量提供相同的内存位置
- gnuplot - Gnuplot - 用户 - 错误:“所有点 y 值未定义!”
- javascript - 如何使用javascript将用户输入的秒数转换为日期和时间?
- javascript - 关闭字体真棒按钮在 Firefox 上不起作用
- java - 给定一个整数数组,反转每个最大的严格升序子数组
- vuejs2 - VueJS 从 props 设置自定义组件默认值