我确实同意使用用户定义的类型可以更好地解决这个问题。
我假设您正在编写一个算法,该算法具有按升序排序的不相交半开区间的某些属性,那么以下提供了Serial
实例。
我决定给出Interval
不同AscDisjIntervals
的生成器,而不是根据另一个来实现。
算法AscDisjIntervals
就像我已经在评论中写的那样
- 生成非负
Integer
s 列表(这是为了避免Int
溢出)
- 对这些整数求和(这会断言所有值的升序
- 从此列表生成对(如果列表具有奇数个元素,则丢弃最后一个元素)
Intervals.hs
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
module Intervals where
newtype Interval = I (Integer,Integer) deriving(Eq)
instance Show Interval where
show (I (a,b)) = "["++show a ++ ", "++ show b ++ "]"
instance Monad m => Serial m Interval where
series = let a_b a b = I (getNonNegative $ min a b , getNonNegative $ max a b)
in cons2 a_b
newtype AscDisjIntervals = ADI [Interval] deriving (Eq)
instance Show AscDisjIntervals where
show (ADI x) = "|- "++ (unwords $ map show x) ++ " ->"
instance Monad m => Serial m AscDisjIntervals where
series = cons1 aux1
aux1 :: [NonNegative Int] -> AscDisjIntervals
aux1 xx = ADI . generator . tail $ scanl (+) 0 xx
where generator [] = []
generator (_:[]) = []
generator (x:y:xs) = let i = I (getNonNegative x ,getNonNegative y)
in i:generator xs
注意:我只编译了程序,没有测试任何属性。