Reputation: 392
Here is the problem I encountered. I have some functions that are similar in their bodies (with a slightly difference), but they have signatures.
flatB :: [[String]] -> [[String]]
flatB [] = []
flatB [x] = [x]
flatB (a : b : xs) | isDigit (head n) = replicate (read n :: Int) a ++ flatB xs
| otherwise = a : flatB (b : xs)
where n = head b
flatC :: [String] -> [String]
flatC [] = []
flatC [x] = [x]
flatC (a : b : xs) | isDigit (head b) = replicate (read b :: Int) a ++ flatC xs
| otherwise = a : flatC (b : xs)
I'm expecting the function to do the following:
> flatC ["a","2","b"]
["a","a","b"]
> flatB [["a","b"],["2"]]
[["a","b"],["a","b"]]
The code above works. But I'm wondering whether there is a simpler way to achieve this?
I think that creating a typeclass may be the way, but I don't know how to do it.
Upvotes: 2
Views: 86
Reputation: 33509
The only difference is how you read the Int
out of every other element on the list, which you can factor out as a function parameter:
import Text.Read (readMaybe)
flat :: (a -> Maybe Int) -> [a] -> [a]
flat _ [] = []
flat _ [x] = [x]
flat readElem (a : b : xs)
| Just n <- readElem b = replicate n a ++ flat readElem xs
| otherwise = a : flat readElem (b : xs)
flatB :: [[String]] -> [[String]]
flatB = flat readHead
where
readHead [] = Nothing
readHead (n : _) = readMaybe n
flatC :: [String] -> [String]
flatC = flat readMaybe
Upvotes: 3