Hello Haskellers and Haskellettes,
I've been fiddling around with Haskell for quite a while but there is this concept of classes I cannot quite grasp. In the following example I have the datatype of ExprTree
data Val a = Num a | Var String deriving (Eq, Ord, Show)
data ExprTree = Leaf {lab::Label, val::(Val a)=> a}
| Node {lab::Label, fun::Fun, lBranch::ExprTree, rBranch::ExprTree}
deriving(Eq,Ord)
which leads to
Type constructor `Val' used as a class In the definition
of data constructor `Leaf' In the data type declaration for `ExprTree'
i also tried
data ExprTree' = Leaf {lab::Label, val::Val}
...
but randomly changing type signature - neither sounds efficent nor provides enlightenment.
now as far as i know Num a
denotes something of class Num
but is this is no instance of a datatype - and doesn't let me compile.
So what do i have to do in order to make ExprTree
well defined.
Thanks in advance for hints and ideas!
Edit:
1) Thanks for the fast answers!
2) I changed the val::(Val a)=>a
to val::Val a
i had something similar in mind - but then the error: Not in scope type variable a
occurs
do you have additional advice ??
What's a typeclass in Haskell? A typeclass defines a set of methods that is shared across multiple types. For a type to belong to a typeclass, it needs to implement the methods of that typeclass. These implementations are ad-hoc: methods can have different implementations for different types.
The class defines object's internal state and the implementation of its operations. In contrast, an object's type only refers to its interface - a set of requests to which it can respond. An object can have many types, and objects of different classes can have the same type.
An interface in the Java programming language is an abstract type that is used to specify an interface (in the generic sense of the term) that classes must implement. These two looks rather similar: type class limit a type's behavior, while interface limit a class' behavior.
Everything in Haskell has a type, so the compiler can reason quite a lot about your program before compiling it. Unlike Java or Pascal, Haskell has type inference.
To answer the question in the title: When talking about Haskell, the word "class" is almost always used to mean "typeclass" as that's the only kind of class there is in Haskell. So there is no difference.
To answer the question in your body:
data ExprTree a =
Leaf {lab::Label, val::(Val a)}
| Node {lab::Label, fun::Fun, lBranch::(ExprTree a), rBranch::(ExprTree a)}
deriving(Eq,Ord)
Writing (Val a)=>a
makes no sense because Val
isn't a typeclass and you can't just introduce typeclass constraints on the right hand side of a type definition (without extensions anyway - and either way it's not what you want).
The correct type would be
data Val a = Num a | Var String deriving (Eq, Ord, Show)
data ExprTree a = Leaf {lab::Label, val :: Val a}
| Node {lab::Label, fun::Fun, lBranch::ExprTree a, rBranch::ExprTree a}
deriving(Eq,Ord)
Since the type Val
requires an additional type parameter, you need to provide one whenever you use it*. I used a type variable, just as in the initial definition; that requires the variable to also be named as a parameter to ExprTree
. (The other possibilities would be to use a concrete type such as Int
or Maybe String
, etc., or to use an existential type; neither makes sense here.)
What you actually used was a typeclass context ("class" is just shorthand for "typeclass"). Val
is a type, not a typeclass, so it's not legal there.
* This isn't quite true; you need a type of kind *
. Kinds are the types of types: Int
has kind *
, Val a
has kind *
, Val
has kind * -> *
. That is, by itself Val
is a type function which requires a parameter in order to become a full type.
The error points to this part of the type definition:
val::(Val a)=> a
This syntax means, "for any instance a
of the typeclass Val
, the value of val
is of type a
." But then (1) Val
isn't a typeclass and (2) the type a
seems to come out of thin air.
What you may have intended to say is
data Val a = Num a | Var String
deriving (Eq, Ord, Show)
data ExprTree a = Leaf { val :: Val a }
| Node { lBranch :: ExprTree a, rBranch :: ExprTree a }
deriving (Eq, Ord)
Your problem is already solved, but I see you use GHC and sometimes — especially in the beginning — Hugs error messages may be somewhat easier to read, in this case:
Syntax error in data type declaration (unexpected `=>')
This might actually have given you a first idea where to look. Mind you that I'm not advocating Hugs over GHC here, but as a Haskell beginner I think that the former provides more helpful error messages.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With