Quindi il problema sto lavorando per far corrispondere un modello a un elenco, come questo: match "abba" "redbluebluered" -> True
o match "abba" "redblueblue" -> False
, ecc. Ho scritto un algoritmo che funziona, e penso che sia ragionevole, ma non sono sicuro se c'è un modo migliore per farlo senza ricorrere esplicitamente alla ricorsione.Esiste un modo per non utilizzare la ricorsione esplicita in questo algoritmo?
import Data.HashMap.Strict as M
match :: (Eq a, Eq k, Hashable k) => [k] -> [a] -> HashMap k [a] -> Bool
match [] [] _ = True
match [] _ _ = False
match _ [] _ = False
match (p:ps) s m =
case M.lookup p m of
Just v ->
case stripPrefix v s of
Just post -> match ps post m
Nothing -> False
Nothing -> any f . tail . splits $ s
where f (pre, post) = match ps post $ M.insert p pre m
splits xs = zip (inits xs) (tails xs)
Lo definirei come match "abba" "redbluebluered" empty
. L'algoritmo attuale è semplice. La mappa contiene gli schemi già abbinati. Alla fine è [a -> "rosso", b -> "blu"]. Se il modello successivo è quello che abbiamo visto prima, prova ad abbinarlo e ricorri se possibile. Altrimenti fallire e restituire false.
Se il modello successivo è nuovo, provare a mappare il nuovo modello su ogni singolo prefisso nella stringa e ricorsivamente verso il basso.
e come un problema di parser comune, qui è necessario controllare l'input analizzato completamente. Modifica le ultime due righe: '(assegna, r) <- ottieni; guardia $ r == []; return assigns' –
'sequenza. la mappa f' è 'mapM f' – Cactus