2011-05-07 53 views
2

作为haskell的初学者(学习对于我的命令式思维受损的大脑很困难)我想问一个更有经验的人如何用更简洁/优雅的方式改善/重写下面的代码。列出n-array树的所有值

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

非常感谢。

回答

4

这是一个重构。主要是你的代码是好的,一些变化在这里是更多的教学目的:

  • 使用方式警卫,使4例明确
  • 替换嵌套的元组与元组
  • 使用箭头职能转变更有效的节点类型的元组比
  • Pointfree为getWords提高了可读性

的代码:

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

自'getWords [] == []'以来,您可以组合更多的案例。 – augustss 2011-05-07 19:16:13

+0

很好,虽然我期望算法非常不同。 Curried版本是一个有趣的改进,Control.Arrow模块无疑是我进一步学习的灵感。 – 2011-05-07 20:55:07

+0

我会接受你的答案,而另一种解决方案,如果有的话,也将不胜感激。 – 2011-05-07 21:01:20