Więc problem, nad którym pracuję, polega na dopasowaniu wzorca do listy, takiej jak ta: match "abba" "redbluebluered" -> True
lub match "abba" "redblueblue" -> False
itp. Napisałem algorytm, który działa, i myślę, że jest to rozsądne zrozumiałe, ale nie jestem pewien jeśli jest lepszy sposób na to bez wyraźnej rekursji.Czy istnieje sposób, aby nie używać jawnej rekurencji w tym algorytmie?
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)
Nazwałbym to tak jak match "abba" "redbluebluered" empty
. Rzeczywisty algorytm jest prosty. Mapa zawiera wzory już dopasowane. Na końcu jest [a -> "czerwony", b -> "niebieski"]. Jeśli następny wzór jest taki, jaki widzieliśmy wcześniej, po prostu spróbuj go dopasować i przerwij, jeśli to możliwe. W przeciwnym razie przestaw i zwróć wartość false.
Jeśli następny wzorzec jest nowy, po prostu spróbuj odwzorować nowy wzorzec na każdy przedrostek w łańcuchu i ponowić.
i podobnie jak w przypadku zwykłego problemu z analizatorem składni, należy sprawdzić, czy dane wejściowe zostały całkowicie przeanalizowane. Zmodyfikuj dwa ostatnie wiersze: '(assigns, r) <- get; guard $ r == []; return przypisuje 'sekwencję' –
. mapa f' to 'mapM f' – Cactus