List all values of n-array tree
as a beginner in haskell (learning is tough for my imperative's thinking damaged brain) I'd like to ask someone more experienced how to improve/rewrite following code in a more concise/elegant way.
-- Data type for n-array tree structure
-- holds Strings of words and their commonness
data Trie = Trie { commonness :: Maybe Int
, children :: [(Char, Trie)]
} deriving (Eq, Read, Show)
-- Returns all words and its commonness from a tree
dict :: Trie -> [(String, Int)]
dict (Trie freq []) = case freq of
Just f -> [("", f)]
_ -> error "String not terminated with commonness !"
dict (Trie (Just freq) chld) = ("", freq):getWords chld
dict (Trie _ chld) = getW开发者_如何学运维ords chld
getWords :: [(Char, Trie)] -> [(String,Int)]
getWords ch = concatMap ( \(c, tr) -> map (\(s, f) -> (c:s, f)) (dict tr) ) ch
It's about "hairy" code of getWords function with nested maps. Some suggestion how to simplify it, write it more concise ?
Thanks in an advance.
Here's a refactoring. Mostly your code is fine, and some of the changes here are more for teaching purposes:
- Use pattern guards to make the 4 cases explicit
- Replace nested tuple transforms with arrow functions on tuples
- Use a more efficient node type than tuples
- Pointfree for getWords improves readability
The code:
{-# LANGUAGE PatternGuards #-}
import Control.Arrow (first)
-- a more efficient type than tuples
data Node = Node {-# UNPACK #-}!Char Trie
deriving (Eq, Read, Show)
data Trie = Trie { commonness :: Maybe Int
, children :: [Node]
}
deriving (Eq, Read, Show)
-- Returns all words and its commonness from a tree
dict :: Trie -> [(String, Int)]
dict (Trie freq [])
| Just f <- freq = [("", f)]
| otherwise = error "String not terminated with commonness !"
dict (Trie freq chld)
| Just f <- freq = ("", f) : getWords chld
| otherwise = getWords chld
getWords :: [Node] -> [(String,Int)]
getWords = concatMap $ \(Node c tr) -> map (first (c :)) (dict tr)
精彩评论