3

I'm having a few issues with trees, I was trying to make a simplified Family tree (genealogy tree) where I start with only 1 person, let's say Grandpa Bob, I'll try my best drawing this:

                                        BOB
                                         |
                                     /        \
                                 SIMON         RUDY
                                /    \         /  \
                            ROBBIE  MARTHA  TOM   ISABEL

So, Grandpa Bob had 2 kids with Grandma(which doesn't matter here), Simon and Rudy, then Simon and Rudy both had 2 kids each (only 1 parent matters again), note that this is not necessarily the tree I want to make but only an example which can be used by you guys to help me out. I want to have it as a data Family, then have a function that initiates the "root" which will be Grandpa Bob and then have another function that will let me add someone to the tree, as in add Simon descending from Bob.

So far this is what I have atm(I've tried other things and changed it all over):

    module Geneaology where
    data Family a = Root a [Family a] | Empty deriving (Show, Read)

    main :: IO()
    main = do
    root :: String -> Family
    root a = ((Root a) [Empty])

Now, this doesn't work at all and gives me a parse error:

t4.hs:9:10: parse error on input ‘=’

I've tried to fix this and change the code around looking for other ways, and saw other posts as well, but didn't make any progress...

I think I made myself clear, thanks in advance xD

developer_hatch
  • 15,898
  • 3
  • 42
  • 75
Wireless
  • 107
  • 10
  • 3
    You've forgotten to say what `main` does! Try for example `main = do print (root "Bob")`. – Daniel Wagner Nov 17 '17 at 19:14
  • 1
    It will be much easier to build your tree the other way around, from the bottom up. Since you can't "modify" Bob's node once you've created it, you can't "add" a descendant to him without tearing apart the whole tree and reassembling it. Conversely, it is easy to create Rudy's subtree from two leaves, and likewise for Simon, and then finally create Bob as the parent of both of those. – amalloy Nov 17 '17 at 19:14
  • 1
    Also, do check out this [classic advice on designing genealogy software](https://stackoverflow.com/q/6163683/791604), if only because it is a delightful read. – Daniel Wagner Nov 17 '17 at 19:15
  • @amalloy what do you mean? Like, add the bottom most "children" first? – Wireless Nov 17 '17 at 19:19
  • as aside: `Root` isn't a great name for that data constructor. Consider `Node` or `Branch` or etc. The root of a tree should be the single convergent point, if one exists ("Bob", in your example.) – Adam Smith Nov 17 '17 at 20:12
  • @AdamSmith in the data Family? Like this: `data Family a = Node a [Family a] ...` instead of Root? – Wireless Nov 17 '17 at 21:41
  • @Wireless yes. You can name it whatever you want. `data Family a = LiterallyAnythingAtAll a [Family a] ...` will still work, but you know what they say: there's only two hard problems in computer science, and one of them is naming things. (The other two are cache invalidation and off-by-one errors). – Adam Smith Nov 17 '17 at 23:52

1 Answers1

2

You have a syntax error, you can create a function in the main with a let and a lambda, and then use it

data Family a = Root a [Family a] | Empty deriving (Show, Read)

main :: IO()
main = do
  let root  = (\a  -> Root a [Empty])
  print(root "Bob")

But you can also define functions outside the main and call them latter:

root :: String -> Family String
root a = Root a [Empty]

main :: IO()
main = do
  print(root "Bob")
luqui
  • 59,485
  • 12
  • 145
  • 204
developer_hatch
  • 15,898
  • 3
  • 42
  • 75
  • I see this works, the thing is I wanted to start it with a function root – Wireless Nov 17 '17 at 19:19
  • 1
    @Wireless ah ok ok, I didn't understood well, so create a function – developer_hatch Nov 17 '17 at 19:52
  • Hey, I've gotten my code like this: `module Geneaology where data Family a = Node a [Family a] | Empty deriving (Show, Read) root :: String -> Family String root a = Node a [Empty] main :: IO() main = do print (root "Bob")` It's giving me the following output: `Node "Bob" [Empty]` How do I make it print only "Bob"? – Wireless Nov 17 '17 at 21:54
  • @Wireless fantastic! So your original question is answered, don't forget to vote and accept ;). Now, that is a totally different question, is better if you ask a new question for that. So is clearly for future readers. But is simple, I can give you a hint, make your own instance of Show and define the show method – developer_hatch Nov 17 '17 at 21:57
  • Alright, was just clearing up all doubts before voting, I always vote don't worry xD Thanks for the help! I think that should be enough, I'll ask a new question if needed :D – Wireless Nov 17 '17 at 22:03
  • @Wireless don't worry at all, I have always loved to help – developer_hatch Nov 17 '17 at 22:04