11

i am new to Haskell and probably missing something really basic here, but i am not able to re-use same value constructor among different data types.

data Colour = Red | Pink | Orange | Yellow
data Fruit  = Apple | Orange | Banana

This produces error saying

Multiple declarations of ‘Orange’

Not sure why this isn't allowed, i have been using OCaml before learning Haskell and was able to define types like this

user17472
  • 139
  • 9

2 Answers2

9

As a quick exercise try just defining one of your data types and then opening up GHCi to inspect it.

data Colour = Red | Pink | Orange | Yellow

If you use :t in GHCi, it will tell you the type of anything.

> :t Red
Red :: Colour
> :t Orange 
Orange :: Colour 

So this tells you that your data constructor Orange is really just a function that takes no arguments and produces a value of type Colour.

So what happens if you add a duplicate declaration?

data Colour = Red | Pink | Orange | Yellow
data Fruit  = Apple | Orange | Banana

Now you have defined a function Orange that takes no arguments and produces a value of type Colour or a value of type Fruit. This won't work at all! It would be the same as defining your own custom function foo and giving it multiple type signatures:

foo :: Int 
foo :: String
foo = "6"

Which obviously doesn't work either.

To get around this, you can define each data type in its own module, and use a qualified import to scope them correctly:

import qualified Colour as C -- Module Colour.hs 
import qualified Fruit as F -- Module Fruit.hs 

orange1 = C.Orange :: C.Colour 
orange2 = F.Orange :: F.Fruit

Now, you might be thinking "The compiler is smart, it should know what Orange I'm talking about when I'm using it." and you'd be partially right. There is an ongoing effort to bring Overloaded or Duplicate record fields into Haskell. There are various other questions of that ilk already defined here, but I'll list a few references for further reading.

jkeuhlen
  • 4,401
  • 23
  • 36
  • Thank for your answer. i am somewhat able to understand it, but still not sure why the constraint exists. you demonstrated that it is not possible to determine the type of Orange which is understandable., but in usage i am forcing a type on Orange and this should be permitted fruitILike :: Fruit fruitILike = Orange myFavouriteColour :: Colour myFavouriteColour = Orange If i don't provide a type sig nature then sure compiler should give an error, but when types are specified should it allow ? – user17472 Jul 30 '18 at 15:57
  • 1
    The constraint exists because the compiler assumes all functions have a single type. When you import qualified, you are specifying different functions. In your implementation, you have defined the function `Orange` twice in the same module, and given it conflicting type signatures. Does that make sense? – jkeuhlen Jul 30 '18 at 16:01
  • Alright i think i am getting to it now. If it is not too much to ask, what should my approach be for modelling this data ? – user17472 Jul 30 '18 at 16:04
  • Yes, data constructors behave as functions as well. For example if you define `data Fruit = Apple Colour`, you would have `Apple` as a function that takes a `Colour` and returns a `Fruit` – jkeuhlen Jul 30 '18 at 16:06
  • 2
    You can either use `OrangeColour` and `OrangeFruit` as the constructors (i.e. make the names different) or you can move the definitions to different modules. Either solution should work for you! – jkeuhlen Jul 30 '18 at 16:07
0

There is no particular reason, that is how language was designed. I think the idea was to make sure compiler can infer type for as many expressions as possible. Note that if language will allow to reuse constructors, then you'll have to specify type for show Orange expression - compiler can't infer it anymore. Though now a lot of people don't take this reason seriously, and a lot of modern language extentions do break compiler's ability to infer types for many expressions. So I guess in few years you'll find that your example works already :)

Yuras
  • 13,856
  • 1
  • 45
  • 58
  • Right, so by declaring Orange twice compiler is not able to infer type automatically, got that. but if i write a type signature and specify type (see comment on jkeuhlen's answer) then it should work, but as you said this is something that is being worked upon – user17472 Jul 30 '18 at 16:12