Let's say that I have a type like this (that works):
data WAE = Num Float
| Id String
| With [(String, WAE)] WAE -- This works, but I want to define it as below
deriving(Eq, Read, Show)
I want a type like this (doesn't work):
data WAE = Num Float
| Id String
| With [(Id, WAE)] WAE -- This doesn't work ("Id not in scope")
deriving(Eq, Read, Show)
Why can't I do that in Haskell? Any ideas in achieveing a similar effect?
In Haskell, there are two distinct namespaces. One for values, and one for types. Data constructors such as Id live in the value namespace, whereas type constructors such as String, as well as classes live in the type namespace. This is OK because there is no context where both would be allowed.
In the definition of a data type, the two namespaces live side by side, as you're defining a both a new type constructor and several new data constructors, while referring to existing type constructors.
data WAE = Num Float
| Id String
| With [(String, WAE)] WAE
deriving(Eq, Read, Show)
Here, WAE, Float, String, (,), [], Eq, Read and Show are all names in the world of types, whereas Num, Id and With are names in the world of values. Mixing them does not make any sense, and this is why Id is not in scope in your second piece of code, as you are in a type context, and there is no type-level thing called Id.
It's not 100% clear from your question what you were trying to do, but I suspect it might be something like this:
type Id = String -- Or perhaps a newtype
data WAE = Num Float
| Id Id
| With [(Id, WAE)] WAE
deriving(Eq, Read, Show)
Note that because the namespaces are distinct, it's perfectly fine to have something called Id in both.
Based on your question, I'm not entirely sure what you are trying to accomplish. Here are two possibilities that are possible with Haskell's type-system.
data WAE = Num Float
| Id String
| With [(WAE, WAE)] WAE
deriving (Eq, Read, Show)
I'm not sure this is what you want, however, because it allows for more than just an id in the first portion of the pair.
Another possibility is to create a new type (or alias) for the id, like so:
data MyId = MyId String deriving (Eq, Read, Show)
data WAE = Num MyId Float
| Id MyId
| With [(MyId, WAE)] WAE
deriving (Eq, Read, Show)
Note that MyId could also be created with either newtype or type, each giving a slightly different meaning.
You cannot, however use Id as it is a data-constructor, where a type is expected.
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