开发者

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)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜