Ho una EDSL procedurale che utilizza blocchi di istruzioni.Come ordinare una lista usando un ordine parziale in Haskell?
Queste istruzioni vengono aggiunte ai blocchi in un ordine particolare sebbene possano esistere delle dipendenze tra le istruzioni.
Durante la compilazione dell'EDSL, tuttavia, è necessario verificare che le istruzioni siano ordinate nell'ordine di dipendenza, ad es.
B := A
C := B
E := D
Dal momento che non tutte le dichiarazioni hanno dipendenze non esiste un ordine totale (ad esempio E := D
sopra è indipendente e può essere posizionato ovunque). Non ci sono dipendenze cicliche quindi l'ordinamento delle liste dovrebbe essere possibile.
Ho provato a hackerare una soluzione utilizzando Data.List.sortBy
e definendo Ordering
che restituirebbe EQ
a significare che le istruzioni non hanno dipendenze. Questo ha funzionato per alcuni esempi ma non nel caso generale, ad es. ordinare il seguente fatto nulla:
C := B B := A
D := C = should produce => C := B
B := A D := C
Questo perché l'ordinamento per inserzione ordinamento predefinito e solo assicura l'elemento inserito è minore o uguale a quello successivo.
ho cercato l'internet per un'implementazione Poset ma non hanno trovato nulla applicabile:
altfloat:Data.Poset definisce Ordering = LT | GT | EQ | NC
(NC
per non comparabili), che è buona, ma la condizione sort
assume NaN
-come elementi non comparabili e li getta via.
logfloat:Data.Number.PartialOrd è simile al precedente tranne che utilizza Maybe Ordering
e non ho visto una funzione di ordinamento in qualsiasi parte del pacchetto.
Math.Combinatorics.Poset Non ho capito come usarlo o se è applicabile.
Di seguito è riportato un esempio minimo che contiene sia istruzioni vincolanti che non vincolanti. L'ordine delle dichiarazioni non binarie è importante e devono mantenere l'ordine originale (vale a dire che l'ordinamento deve essere stabile con le dichiarazioni w.r.t. che non hanno una relazione di dipendenza).
spero che ci sia una semplice soluzione a questo senza utilizzare un grafico in piena regola dipendenza ...
module Stmts where
import Data.List (sortBy)
data Var = A | B | C | D | E | F | G | H deriving (Eq, Show)
data Stmt = Var := Var
| Inc Var
deriving (Show)
-- LHS variable
binds :: Stmt -> Maybe Var
binds (v := _) = Just v
binds _ = Nothing
-- RHS variables
references :: Stmt -> [Var]
references (_ := v) = [v]
references (Inc v) = [v]
order :: [Stmt] -> [Stmt]
order = sortBy orderStmts
orderStmts :: Stmt -> Stmt -> Ordering
orderStmts s1 s2 = ord mbv1 mbv2
where
ord Nothing Nothing = EQ -- No dep since they don't bind vars
ord (Just v1) Nothing = LT -- Binding statements have precedence
ord Nothing (Just v2) = GT -- ^^^
ord (Just v1) (Just v2) -- Both statements are binding:
| v1 `elem` refs2 = LT -- * s2 depends on s1
| v2 `elem` refs1 = GT -- * s1 depends on s2
| otherwise = EQ -- * neither
-- *Maybe* they bind variables
mbv1 = binds s1
mbv2 = binds s2
-- Variables they reference
refs1 = references s1
refs2 = references s2
-- The following should return [B := A, C := B, D := C, Inc F, Inc G]
test = order [Inc F, Inc G, C := B, D := C, B := A]
Per essere assolutamente chiari: stai cercando un tipo_stable che lasci l'ordine invariato per elementi inimitabili? – MathematicalOrchid
Ho cercato un po 'e ho trovato [questa domanda SO precedente] (http://stackoverflow.com/questions/11230881/stable-topological-sort). Ho anche trovato commenti sul web dubitando che "un ordinamento topologico stabile" (che sarebbe se esistesse) fosse una cosa ben definita. Certamente [l'articolo di Wikipedia sull'ordinamento topologico] (https://en.wikipedia.org/wiki/Topological_sorting) non contiene la parola "stabile" da nessuna parte. La mia domanda in questo senso: è effettivamente * possibile * mantenere sempre l'ordine di termini incomparabili? –
Hm Immagino che se le istruzioni debbano essere stabili solo se hanno * no * relazione di dipendenza con altre affermazioni, allora non ci sono problemi. Per il problema più forte di ordinamento topologico stabile generale ho trovato un controesempio: Nodi ABCDEF con A> C, B> D, E