Haskell家谱 - 考试准备

时间:2014-08-08 09:38:20

标签: haskell tree

我正在参加考试,需要帮助解决有关家谱的考试问题。我以前做过树,但只有这种格式:

data Tree a = Empty | Leaf a | Node a (Tree a) (Tree a)

所以基本上是一个空的或叶子节点的树,或者有一个递归跟随它的2个树的节点。 现在我收到了这个问题:

                                DAN=DORIS

               /                   |                          \
        JACK-PEGGY            CHRISTINE-PAUL                PHIL-JILL 
      /     |     \                                      /    /     |     \  
 JENNIFER LILLIAN TONY                              SCULA KENTON DAVID ELIZABETH

This shows that Dan married Doris and their children were Jack (who married Peggy), 
Christine (who married Paul) and Phil (who married Jill). The children of Jack and Peggy 
were Jennifer, Lillian and Tony. Christine and Paul had no children. Phil and Jill’s 
children were Shula, Kenton, David and Elizabeth. 
Assume that any name appears in the tree at most once. Neglect the possibility of 
second marriages. 

(i) Give a Haskell algebraic datatype definition for family trees, and show how the 
    above tree would be represented using your datatype
(ii) Using your datatype definition, write a Haskell function which, given the name 
     of a person and a family tree, returns the names of that person’s children, if 
     any.

对不起,这是我能画出的最好的纸张 - 但很明显,Dan与最顶层的Doris结婚,然后有3个孩子Jack,Christine和Phil等。

所以我使用的树型不能在这里使用,我想知道这次是什么类型的定义(基本上是问题2.(i),以及(ii)的任何想法?

2 个答案:

答案 0 :(得分:7)

树中的子项数是可变的。标准库类型Data.Tree,对这些树进行大致模拟:

data Tree a = Node a [Tree a]

这也适用于你的情况,除了

  • 你需要区分已婚夫妇(有多少个孩子)和一个人(没有孩子)的情况
  • 您可能还想添加一个空树

因此,在不放弃太多的情况下,一棵树可以有三种形式:空的,已婚夫妇和任何数量的孩子,以及没有孩子的单身人士。将最后一句从英语翻译成Haskell,你就完成了。

答案 1 :(得分:1)

import Data.Foldable as F

data Family a = Single a | Couple a a [Family a]
    deriving Show -- useful for ghci

isCouple :: Family a -> Bool
isCouple (Couple _ _ _) = True
isCouple _ = False

isFamily :: Eq a => a -> Family a -> Bool
isFamily n (Single a) = n == a
isFamily n (Couple a b _) = n == a || n == b

q1 :: Family String
q1 = Couple "Dan" "Doris" [Couple "Peggy" "Jack" [Single "Jennifer", Single "Lillian", Single "Tony"], Couple "Christine" "Paul" [], Couple "Phil" "Jill" [Single "Scula", Single "Kenton", Single "David", Single "Elizabeth"]]

q2 :: String -> Maybe [Family String]
q2 n = q2' n [q1]

q2' :: Eq a => a -> [Family a] -> Maybe [Family a]
q2' n f = case find (isFamily n) f of
    Just (Single _) -> Just []
    Just (Couple _ _ c) -> Just c
    _ -> case filter isCouple f of
        [] -> Nothing
        cs -> q2' n $ F.concatMap (\(Couple _ _ c) -> c) cs