この問題は、ユーザー定義型を使用するとよりよく解決されることに同意します。
昇順でソートされた互いに素な半開間隔のプロパティを持つアルゴリズムを作成していると仮定します。次に、Serial
インスタンスを示します。
私は、一方をもう一方の観点から実装するのではなくInterval
、さまざまなジェネレーターを提供することにしました。AscDisjIntervals
のアルゴリズムAscDisjIntervals
は、すでにコメントに書いたとおりです
- 負でない s のリストを生成する(これはオーバーフロー
Integer
を避けるためです)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
注: プログラムをコンパイルしただけで、プロパティはテストしていません。