Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell data type

Tags:

types

haskell

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?


2 Answers

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.

like image 168
hammar Avatar answered Jul 10 '26 16:07

hammar


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.

like image 33
Adam Wagner Avatar answered Jul 10 '26 15:07

Adam Wagner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!