import Text.Printf (printf) match :: String -> String -> Bool match ('^':xs) y = matchhere xs y match x y = matchhere x y matchhere :: String -> String -> Bool matchhere (x:'*':xs) y = matchstar x xs y matchhere ('$':xs) y = y == [] matchhere ('.':xs) (y:ys) = matchhere xs ys matchhere (x:xs) (y:ys) = x == y && matchhere xs ys matchhere [] _ = True matchhere _ [] = False matchstar :: Char -> String -> String -> Bool matchstar c [] (y:ys) = c `elem` [y,'.'] matchstar c x (y:ys) | c `elem` [y,'.'] = matchhere x ys || matchstar c x ys | otherwise = matchhere x (y:ys) matchstar c _ _ = c == '.' main = mapM_ check [("foo","foo", True), ("foo","bar", False), ("", "foo", True), (".", "Foo", True), (".*","Foo", True), ("Foo$", "Foo", True), ("F.", "Foo", True), ("F.", "foo", False), ("F.*", "Foo", True), ("^Fo", "Fow", True), ("^Fow$", "Fow", True), ("^Fo", "fFow", False), (".", "", False), ("a*a", "aaa", True), ("Fo*", "Foo", True), ("Fo*d", "Foo", False), ("Fo*d", "Foooood", True)] check (pat,str,res) = if match pat str == res then putStr "." else error $ printf "Failure: '%s' =~ /%s/ wasn't %s." str pat (b2s res) where b2s True = "True" b2s False = "False"