patternMinorCanonical
I can has(kell) moar cheezburgers?
Viewed 0 times
kellmoarcancheezburgershas
Problem
KITTEH HAS IMPROOVD CODE SKILLS, AN NAO HAS BETTR CODE 4 U
This is an improvement of my original Haskell Lolcats Translator, and now features a function to do the translation (recursively?) using a map. I still have two
Sample IO:
Teh Codez
This is an improvement of my original Haskell Lolcats Translator, and now features a function to do the translation (recursively?) using a map. I still have two
let statements, which I know are frowned upon, but I couldn't get both the strToUpper and inline fmap working, so I opted for strToUpper.Sample IO:
Enter your text to translate:
Let me have some cake on a plate please
LEMME HAS SUM CAEK ON PLAET PLZTeh Codez
import Data.Map
import Data.Strings
type Dictionary = [(String, String)]
lolcatDictionary =
[
(" A ", " "),
("CAN I", "I CAN"),
("MORE", "MOAR"),
("CHEESEBURGER", "CHEEZBURGER"),
("HAVE", "HAS"),
("HI", "HAI"),
("GHOST", "GOAST"),
("FEET", "FEAT"),
("MOAN", "MOWN"),
("CROWD", "CROUD"),
("NOTHING", "NUTHING"),
("MY", "MAI"),
("THEM", "DEM"),
("THESE", "THEES"),
("YOU", "YU"),
("LET ME", "LEMME"),
("KITE", "KIET"),
("CAT", "KAT"),
("CATS", "KATS"),
("KITTEN", "KITTEH"),
("KITTY", "KITTEH"),
("KITTENS", "KITTEHS"),
("LIKE", "LIEK"),
("COME", "COEM"),
("CAME", "CAEM"),
("BAKE", "BAEK"),
("PLATE", "PLAET"),
("SOME", "SUM"),
("CAKE", "CAEK"),
("PLEASE", "PLZ")
]
main :: IO ()
main = do
putStrLn "Enter your text to translate:"
input String -> String
stringMapReplace [] string = string
stringMapReplace (m:ms) s = stringMapReplace ms (strReplace (fst m) (snd m) s)Solution
What is the
The
In this case, the function can be tersely written as
Intermediate steps to get there
First, recognize that your dictionary is the thing that is being iterated through. (That is, your
as
Now, we can see that
… we can make
Notice that in
But what is
What is the relationship between
QED.
Data.Map doing there? It looks like you were going to use it, but then changed your mind and used a list of pairs instead.The
stringMapReplace function is doing explicit recursion. A more advanced Haskeller would recognize this pattern as some kind of fold:-- if the list is empty, the result is the initial value z; else
-- apply f to the first element and the result of folding the rest
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
-- if the list is empty, the result is the initial value; else
-- we recurse immediately, making the new initial value the result
-- of combining the old initial value with the first element.
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xsIn this case, the function can be tersely written as
stringMapReplace :: Dictionary -> String -> String
stringMapReplace = flip $ foldr $ uncurry strReplaceIntermediate steps to get there
First, recognize that your dictionary is the thing that is being iterated through. (That is, your
(m:ms) plays the role of the (x:xs) in the fold.) In Haskell, it is usually more convenient to place the parameter that varies the most at the end. So, rewrite your originalstringMapReplace (m:ms) s = stringMapReplace ms (strReplace (fst m) (snd m) s)as
stringMapReplace :: Dictionary -> String -> String
stringMapReplace map s = stringMapReplace' s map
where
stringMapReplace' s [] = s
stringMapReplace' s (m:ms) = stringMapReplace' (strReplace (fst m) (snd m) s) msNow, we can see that
stringMapReplace' fits the pattern for foldl. However, foldr is preferable to foldl. If we perform the substitutions in a different order…stringMapReplace :: Dictionary -> String -> String
stringMapReplace map s = stringMapReplace' s map
where
stringMapReplace' s [] = s
stringMapReplace' s (m:ms) = strReplace (fst m) (snd m) (stringMapReplace' s ms)… we can make
stringMapReplace' fit the pattern for foldr.stringMapReplace map s = stringMapReplace' s map
where
stringMapReplace' s map = foldr f s map
f m = strReplace (fst m) (snd m)Notice that in
stringMapReplace' s map = foldr f s map, the s map is repeated on both sides. We can write that in point-free style as stringMapReplace' = foldr f.But what is
f? We can simplify it as uncurry strReplace.stringMapReplace map s = stringMapReplace' s map
where
stringMapReplace' = foldr $ uncurry strReplaceWhat is the relationship between
stringMapReplace and stringMapReplace'? The parameters are flipped.stringMapReplace = flip $ foldr $ uncurry strReplaceQED.
Code Snippets
-- if the list is empty, the result is the initial value z; else
-- apply f to the first element and the result of folding the rest
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
-- if the list is empty, the result is the initial value; else
-- we recurse immediately, making the new initial value the result
-- of combining the old initial value with the first element.
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xsstringMapReplace :: Dictionary -> String -> String
stringMapReplace = flip $ foldr $ uncurry strReplacestringMapReplace (m:ms) s = stringMapReplace ms (strReplace (fst m) (snd m) s)stringMapReplace :: Dictionary -> String -> String
stringMapReplace map s = stringMapReplace' s map
where
stringMapReplace' s [] = s
stringMapReplace' s (m:ms) = stringMapReplace' (strReplace (fst m) (snd m) s) msstringMapReplace :: Dictionary -> String -> String
stringMapReplace map s = stringMapReplace' s map
where
stringMapReplace' s [] = s
stringMapReplace' s (m:ms) = strReplace (fst m) (snd m) (stringMapReplace' s ms)Context
StackExchange Code Review Q#131859, answer score: 2
Revisions (0)
No revisions yet.