非決定性をモデル化するためにリストを使用することは、入力が無限に多くの値をとることができる場合には問題があります。例無限の入力に対する非決定性
pairs = [ (a,b) | a <- [0..], b <- [0..] ]
のためにこれは[(0,1),(0,2),(0,3),...]
を返し、あなたの最初の要素が0
ではない任意のペアを示す程度取得することはありません。
Cantor pairing functionを使用すると、リストのリストを1つのリストにまとめてこの問題を回避できます。例えば、我々は今、モナドとしてこれを包む場合は、我々はすべての可能なペア
newtype Select a = Select { runSelect :: [a] }
instance Monad Select where
return a = Select [a]
Select as >>= f = Select $ as >>>= (runSelect . f)
pairs = runSelect $ do
a <- Select [0..]
b <- Select [0..]
return (a,b)
この結果を列挙することができます
(>>>=) :: [a] -> (a -> [b]) -> [b]
as >>>= f = cantor (map f as)
cantor :: [[a]] -> [a]
cantor xs = go 1 xs
where
go _ [] = []
go n xs = hs ++ go (n+1) ts
where
ys = filter (not.null) xs
hs = take n $ map head ys
ts = mapN n tail ys
mapN :: Int -> (a -> a) -> [a] -> [a]
mapN _ _ [] = []
mapN n f [email protected](h:t)
| n <= 0 = xs
| otherwise = f h : mapN (n-1) f t
することで、よりインテリジェントにその出力を順序付けバインド-like演算子を定義することができますin
>> take 15 pairs
[(0,0),(0,1),(1,0),(0,2),(1,1),(2,0),(0,3),(1,2),(2,1),(3,0),(0,4),(1,3),(2,2),(3,1),(4,0)]
これはもっと望ましい結果です。 (2,0,1)
が前に表示されていることを
>> take 15 triples
[(0,0,0),(0,0,1),(1,0,0),(0,1,0),(1,0,1),(2,0,0),(0,0,2),(1,1,0),(2,0,1),(3,0,0),(0,1,1),(1,0,2),(2,1,0),(3,0,1),(4,0,0)]
注 - 私たちが代わりにトリプルをお願いしていた場合は、出力の順序は、「素敵」と、それはすべての出力が最終的に含まれていることを私にしてもはっきりしていないようではありません(0,1,1)
- 私の直感では、この問題に対する良い解決策は、 "size"という概念に基づいて出力を並べ替えることで、アルゴリズムへの明示的な入力となるか、暗黙的に与えることができると言います(この例のように、ここで、入力の「サイズ」は入力リストにおけるその位置である)。入力を組み合わせる場合、組み合わせの「サイズ」は、入力のサイズの関数(おそらく合計)でなければなりません。
この問題に対する洗練された解決策はありますか?
[]をlogictに置き換えることはできますか? –
おそらく!それがどのように実装されているかを見ていきます。私は何かのためにそれを使用したいからではなく、教育上の理由からこれに大いに興味があります。 –
これは本当にクールです。いいモナドなインターフェイスを与える方法はわかりませんが、スペース充填曲線のコンセプトは、あなたが望む振る舞いを(n次元にすることができるので)与えることができますか? – jberryman