Haskell Data Types and Functions

Moderator
Posts: 373
Joined: 2006.08
Post: #1
So, I'm still writing that parser I started on about a week ago, and now I need to define my own data types. Basically, I'm just trying to experiment with how Haskell handles Data types, since it seems to be very different from C++ and other OO languages.
I was going along fine until I wrote some code that gave me this error:
Code:
ERROR file:.\meshConversions.hs:24 - Type error in final generator
*** Term           : returnedNode
*** Type           : Node
*** Does not match : a b
I'm clueless as to the meaning of it....at first I thought that it wanted me to return two different parameters from my function, but that didn't seem to fix the error, so I'm guessing that wasn't it Sneaky

Here's the function declaration:
Code:
--arguments are these: firstWord, firstLine, unprocessedContents, currentNode
processFile :: String -> String -> [String] -> Node -> Node

processFile ('#':x) firstLine unprocessedContents currentNode = do
    let returnedNode = Node "test" []
    returnedNode

processFile "DEF" firstLine unprocessedContents currentNode = do
    let returnedNode = Node "got DEF" []
    returnedNode

processFile _ firstLine _ currentNode = do
    let returnedText = "defaulted to generic because :" ++ firstLine ++ ": was not recognized\n";
    let returnedNode = Node returnedText []
    returnedNode

and then here's the entire code, in case you need that:
Code:
module Main where

import IO

--most of these will read perfecty into lists using readIO

data Node = Node {textOutput::String, childNodes::[Node]}

processExtensions [] = error "You must enter a filename"
processExtensions processFile =
    let extension = dropWhile (/= '.') processFile
        in case extension of
        ".wrl" -> processFile
        ""     -> processFile ++ ".wrl"
        _      -> error "Only .wrl files are supported"

prepareFile :: String -> [String]
prepareFile [] = error "The file is empty..."
prepareFile fileContentsOne = lines fileContentsOne

--arguments are these: firstWord, firstLine, unprocessedContents, currentNode
processFile :: String -> String -> [String] -> Node -> Node

processFile ('#':x) firstLine unprocessedContents currentNode = do
    let returnedNode = Node "test" []
    returnedNode

processFile "DEF" firstLine unprocessedContents currentNode = do
    let returnedNode = Node "got DEF" []
    returnedNode

processFile _ firstLine _ currentNode = do
    let returnedText = "defaulted to generic because :" ++ firstLine ++ ": was not recognized\n";
    let returnedNode = Node returnedText []
    returnedNode

main = do
    hSetBuffering stdin LineBuffering
    putStrLn "Enter a filename to be parsed"
    unprocessedFileName <- getLine
    let fileName = processExtensions unprocessedFileName
    contents <- readFile fileName

    --parse into seperate lines
    let preparedContents = prepareFile contents

    --process the file for printing
    let firstLineWhole = head(preparedContents)
    let firstLine = words firstLineWhole
    let firstWord = head(firstLine)
    let unprocessedContents = tail(preparedContents)
    let headNode = Node "" []
    let processedContents = processFile firstWord firstLineWhole unprocessedContents headNode
    putStrLn "Finished"

What I was trying to do was to make a data type called Node, which has a string and then a list of Nodes inside of it. Then I make a Node and return it from the function so that it can be modified/accessed elsewhere. Perhaps I'm understanding how Data types are supposed to function in Haskell?
Can you modify variables in a Data type that has been passed to a function and still have them modified in the place before they were passed to the function? I'm guessing not, but I haven't had a chance to try because of the above error....

Thanks in advance; hopefully it's not too much code to look through Smile
-wyrmmage

Worlds at War (Current Project) - http://www.awkward-games.com/forum/
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
You've declared processFile to return Node, then used "do" syntax, which means you're returning a value ("b" in the message) in some unspecified monad ("a" in the message). Get rid of the "do"s you don't intend, and fix the syntax accordingly, and it'll compile fine:

Code:
module Main where

import IO

--most of these will read perfecty into lists using readIO

data Node = Node {textOutput::String, childNodes::[Node]}

processExtensions [] = error "You must enter a filename"
processExtensions processFile =
    let extension = dropWhile (/= '.') processFile
        in case extension of
        ".wrl" -> processFile
        ""     -> processFile ++ ".wrl"
        _      -> error "Only .wrl files are supported"

prepareFile :: String -> [String]
prepareFile [] = error "The file is empty..."
prepareFile fileContentsOne = lines fileContentsOne

--arguments are these: firstWord, firstLine, unprocessedContents, currentNode
processFile :: String -> String -> [String] -> Node -> Node

processFile ('#':x) firstLine unprocessedContents currentNode =
    Node "test" []

processFile "DEF" firstLine unprocessedContents currentNode =
    Node "got DEF" []

processFile _ firstLine _ currentNode =
    let returnedText = "defaulted to generic because :" ++ firstLine ++ ": was not recognized\n";
    in Node returnedText []

main = do
    hSetBuffering stdin LineBuffering
    putStrLn "Enter a filename to be parsed"
    unprocessedFileName <- getLine
    let fileName = processExtensions unprocessedFileName
    contents <- readFile fileName

    --parse into seperate lines
    let preparedContents = prepareFile contents

    --process the file for printing
    let firstLineWhole = head(preparedContents)
    let firstLine = words firstLineWhole
    let firstWord = head(firstLine)
    let unprocessedContents = tail(preparedContents)
    let headNode = Node "" []
    let processedContents = processFile firstWord firstLineWhole unprocessedContents headNode
    putStrLn "Finished"

Incidentally, the reason I suggested you use Haskell for parsing is due to the existence of the Parsec parser combinator library. Obviously you can still benefit from learning the language a bit, but you probably want to switch to Parsec sooner or later.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  virtual functions not working supersonic 2 4,868 Mar 10, 2011 06:22 AM
Last Post: compiler
  exporting c functions and variables NelsonMandella 6 4,806 Apr 1, 2010 05:07 PM
Last Post: NelsonMandella
  Haskell IO String Problem michxs 2 5,054 Mar 11, 2008 06:24 PM
Last Post: wyrmmage
  Haskell IO type Problems wyrmmage 9 5,855 Mar 3, 2008 05:09 PM
Last Post: OneSadCookie
  Inner types in Java: how to reduce verbosity? JeroMiya 13 4,780 Jul 17, 2007 08:40 PM
Last Post: AndyKorth