views:

181

answers:

3

1) Here is my code, the find function needs to take a (Node a) and a type (a) as parameters but my function definition doesn't seem to work, what am I doing wrong? Little info on the net that I can find, so thanks for any help!

2) When my find function is implemented I'll need to access a specific variable in a Node, how do I do this?!?

-- int for comparisons
find :: (Node a) => Node a -> a -> Bool
find n s
| s == "asd" = True
| s /= "asd" = False

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

myTree = Node "parent" (Node "left" Empty Empty)
(Node "right" Empty Empty)

Here is the error message I get:

Type constructor `Node' used as a class
In the type `(Node a) => Node a -> a -> Bool'
In the type signature for `find':
find :: (Node a) => Node a -> a -> Bool
Failed, modules loaded: none.

I'm obviously still learning this so an explanation of the solutions would also be appreciated, thankyou!

+5  A: 

The syntax

Node a => ...

would mean that Node is a typeclass, but in fact, it's just an ordinary data type.

Hence this signature is sufficient

find :: Node a -> a -> Bool

Example:

find (Node val left right) = ...
find Empty = ...
Dario
Thankyou Dario. I think that was my original solution actually. But now I get this error message (don't mean to be dense, this language is new to me) Couldn't match expected type `a' against inferred type `[Char]' `a' is a rigid type variable bound by the type signature for `find' at C:\Users\Thomas\Documents\Haskell\BinarySearchTree.hs:2:13 In the second argument of `(==)', namely `"asd"' In the expression: s == "asd" In a stmt of a pattern guard for the definition of `find': s == "asd"Failed, modules loaded: none.
Thomas King
By its signature, you defined `find` to work for any type a. But there is only one type that can match with "abc": `string`
Dario
I might add not explicitly doing type signatures when you start off until you understand everything. Try to see why the compiler deduces what it does, then write to the file when you understand. It's like learning everything, there are parts you don't understand and parts you do. Have fun =)
codebliss
A: 

With help from dario provided here was my final solution which works

find :: (Eq a) => Node a -> a -> Bool
find (Node val left right) s
    | s == val  = True
    | s /= val  = False
Thomas King
+3  A: 

Question #1

...
find :: (Node a) => Node a -> a -> Bool

The '(Node a) =>' bit says that a can be anything provided it implements the Node typeclass. Your code doesn't have any typeclass called Node defined, so the quickest way to get past this error is just to remove that constraint:

...
find :: Node a -> a -> Bool
find n s

You will get more errors, however, because of what you are doing with s:

....
| s == "asd" = True

Your type signature says that s can be anything at all, but then you tried to test it for equality with "asd", which means that s has to be a String. Changing your type signature to the following will allow your code to compile, but probably won't accomplish what you want.

find :: Node a -> String -> Bool
...

Question #2

It looks like your goal is to recursively scan through the Node structure testing for equality with some known value until you find what you want. Here is the first 2 lines of what that function should probably look like.

find :: (Eq a) => Node a -> a -> Bool
find (Node n _ _) s | n == s = True
...

"(Eq a) =>" means that a must be something that has ==, /= etc. defined for it.

The second line demonstrates an answer your question on how to "access specific variables in a Node". You use a feature of Haskell called 'pattern matching' to bulid a template of what one of the arguments should look like. The compiler then fits the actual argument to the template you provided.

Michael Steele