1

Consider the following. Why does it not work. And how could I make it work?

type IntOrString
  = String
  | Int

getInt : IntOrString -> String
getInt intOrString =
  case intOrString of
    String ->
      intOrString

    Int ->
      toString intOrString
Chad Gilbert
  • 36,115
  • 4
  • 89
  • 97
Prabhjot
  • 39
  • 1
  • 4

1 Answers1

7

Your declaration of the IntOrString type seems to indicate that you want a type that can hold either an integer or a string. However, that's not what you have created. I recommend reading the section on Union Types in the Elm Guide.

When you declare a union type, you have to create constructors. In your example, you're actually creating a type with two constructors, neither of which contain a parameter, so although you call them Int and String, they bear no relationship to Elm's native Int and String types. In this case, they can be considered roughly equivalent to an enum inside a language like C# or Java.

Furthermore, your declaration causes compiler confusion because you have created constructor names that clash with existing types, so elsewhere in your code the compiler gets confused by which thing you mean when you say Int or String.

Let's redefine the type so that it becomes a single type that can hold an integer or string value. I'll also rename the constructors to avoid name collisions.

type IntOrString
  = MyString String
  | MyInt Int

And now you can tweak the getInt function based on the new definition. Notice how pattern matching is used to pull the string or integer value out of the IntOrString value based on which constructor was used to create it:

getInt : IntOrString -> String
getInt intOrString =
  case intOrString of
    MyString s ->
      s

    MyInt i ->
      toString i
Chad Gilbert
  • 36,115
  • 4
  • 89
  • 97
  • Hi Chad, thanks for clarifying. I was thinking of Union types in languages like typescript where you can combine with any built in type. but that is something different with a same name. – Prabhjot Jul 03 '16 at 21:15