列出n-array树的所有值

时间:2011-05-07 18:57:31

标签: haskell coding-style

作为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函数的“毛茸茸”代码。 一些建议如何简化它,写得更简洁?

先谢谢。

1 个答案:

答案 0 :(得分:4)

这是重构。大部分代码都很好,这里的一些更改更多用于教学目的:

  • 使用模式保护使4个案例明确
  • 使用元组上的箭头函数替换嵌套元组转换
  • 使用比元组更高效的节点类型
  • getWords的Pointfree提高了可读性

代码:

{-# 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)