作为haskell的初学者(学习对于我的命令思维受损的大脑很难)我想问一个更有经验的人如何以更简洁/更优雅的方式改进/重写下面的代码。
-- 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) = getWords chld
getWords :: [(Char, Trie)] -> [(String,Int)]
getWords ch = concatMap ( \(c, tr) -> map (\(s, f) -> (c:s, f)) (dict tr) ) ch
它是关于嵌套地图的getWords函数的“毛茸茸”代码。 一些建议如何简化它,写得更简洁?
先谢谢。
答案 0 :(得分:4)
这是重构。大部分代码都很好,这里的一些更改更多用于教学目的:
代码:
{-# 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)