のは、我々は無限のセットに対応するためにGHC's Set codeを適応させるときに何が起こるか見てみましょう:
module InfSet where
data InfSet a = Bin a (InfSet a) (InfSet a)
-- create an infinite set by unfolding a value
ofUnfold :: (x -> (x, a, x)) -> x -> InfSet a
ofUnfold f x =
let (lx,a,rx) = f x
l = ofUnfold f lx
r = ofUnfold f rx
in Bin a l r
-- check for membership in the infinite set
member :: Ord a => a -> InfSet a -> Bool
member x (Bin y l r) = case compare x y of
LT -> member x l
GT -> member x r
EQ -> True
-- construct an infinite set representing a range of numbers
range :: Fractional a => (a, a) -> InfSet a
range = ofUnfold $ \(lo,hi) ->
let mid = (hi+lo)/2
in ((lo, mid), mid, (mid, hi))
注意私が代わりに単一の値を展開する機能ofUnfold
をどう定義するか、代わりに無限のリストから無限集合を構築する、 無限のリストに。 これは、両方のブランチを遅延並列に構築することを可能にします(別のブランチを構築する前に、ブランチを完成させる必要はありません。 )。
のは、それに旋回を与えてみましょう:
ghci> :l InfSet
[1 of 1] Compiling InfSet (InfSet.hs, interpreted)
Ok, modules loaded: InfSet.
ghci> let r = range (0,128)
ghci> member 64 r
True
ghci> member 63 r
True
ghci> member 62 r
True
ghci> member (1/2) r
True
ghci> member (3/4) r
True
まあ、それが動作しているようです。 Setの外で値を試してみたらどうでしょうか?
ghci> member 129 r
^CInterrupted.
これは実行され、実行され、終了しません。 inifiniteセットには停止するブランチがありません。 検索が終わることはありません。私たちは、何とか元の範囲を確認することができ、それが個別素子の無限集合のための実用的ではありません。
ghci> let ex = ofUnfold (\f -> (f . (LT:), f [EQ], f . (GT:))) id
ghci> :t ex
ex :: InfSet [Ordering]
ghci> member [EQ] ex
True
ghci> member [LT,EQ] ex
True
ghci> member [EQ,LT] ex
^CInterrupted.
だから、無限のセットが可能ですが、私は彼らが便利しているかわかりません。
[ソースのSet.fromList](http://hackage.haskell.org/packages/archive/containers/latest/doc/html/src/Data-Set.html#fromList)に記載されています。 'foldlStrict'で実装されています。 (なぜ 'foldl 'を使用しないのか分かりませんが、明らかに同じです。) –