Die Verwendung von Listen zur Modellierung von Nichtdeterminismus ist problematisch, wenn die Eingaben unendlich viele Werte annehmen können. Zum BeispielNichtdeterminismus für unendliche Eingaben
pairs = [ (a,b) | a <- [0..], b <- [0..] ]
Dies wird [(0,1),(0,2),(0,3),...]
zurückkehren und nie Paar bekommen, um dem zu zeigen Ihnen erstes Element ist nicht 0
.
Verwenden Sie die Cantor pairing function, um eine Liste von Listen in eine einzelne Liste zu reduzieren, um dieses Problem zu umgehen. Zum Beispiel können wir eine bind artigen Operator definieren, die seine Ausgaben intelligenter Aufträge durch
(>>>=) :: [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
Wenn wir das jetzt einpacken als Monade, können wir alle möglichen Paare
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)
Diese Ergebnisse aufzählen 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)]
was ein viel wünschenswertes Ergebnis ist. Wenn wir jedoch stattdessen für Tripel stellen waren, die Ordnung an den Ausgängen ist nicht so „nett“ und es ist nicht einmal mir klar, dass alle Ausgänge schließlich enthalten sind -
>> 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)]
Beachten Sie, dass (2,0,1)
erscheint vor (0,1,1)
in der Reihenfolge - meine Intuition sagt, dass eine gute Lösung für dieses Problem die Ausgaben nach einem Begriff der "Größe" ordnen wird, die eine explizite Eingabe in den Algorithmus sein könnte oder implizit gegeben werden könnte (wie in diesem Beispiel) wobei die "Größe" einer Eingabe ihre Position in den Eingabelisten ist. Bei der Kombination von Eingängen sollte die "Größe" einer Kombination eine Funktion (wahrscheinlich die Summe) der Größe der Eingänge sein.
Gibt es eine elegante Lösung für dieses Problem, das ich vermisse?
Konnte möglicherweise [] durch logict ersetzen? –
Vielleicht! Ich schaue mir an, wie das implementiert ist. Bin aus pädagogischen Gründen eher daran interessiert, als weil ich es für etwas nutzen möchte. –
Das ist wirklich cool; Ich weiß nicht, wie man eine schöne monadische Schnittstelle gibt, aber vielleicht kann das Konzept der raumfüllenden Kurven Ihnen das gewünschte Verhalten geben (wie sie n-dimensional sein können)? – jberryman