In Haskell, is it possible to define a data type within a function scope?
For example, I am writing a function f :: [(Char, Int)] -> [(Char, String)]
. In the implementation of the function, I will build a tree from the input list, and then traverse the tree to build the output list. One solution is to define a new Tree data type specific to my problem, along with two helper functions, one to translate the input list into the Tree and the other to walk the Tree and build the output list.
Now the two helper functions can easily be pulled into the scope of f
by putting them into a where clause, but what about the interim nonce type Tree? It seems ugly to pollute the namespace by defining it outside the function scope, but I don't know how else to do it.
For context, it turns out I am computing a Huffman encoding. I am not particularly interested in finding an alternative algorithm at this point, as I suspect that it will often be useful in Haskell to define helper data types between helper functions, so I am interested in general approaches to this.
In general, we define a new data type by using the data keyword, followed by the name of the type we're defining. The type has to begin with a capital letter to distinguish it from normal expression names. To start defining our type, we must provide a constructor.
In a data declaration, a type constructor is the thing on the left hand side of the equals sign. The data constructor(s) are the things on the right hand side of the equals sign. You use type constructors where a type is expected, and you use data constructors where a value is expected.
Haskell permits user defined datatypes. We can define structured types such as trees, stacks, queues .... To do this, we define new names, called constructors, to denote the components of the new type. In general, a constructor takes arguments.
Haskell is a functional language and it is strictly typed, which means the data type used in the entire application will be known to the compiler at compile time.
No, it's impossible.
In Haskell modules and qualified imports are supposed to resolve all namespacing problems, like yours or the notorious record field names collision.
So you want a type to be visible only to a certain function? Put that type and that function in a new module and (optionally) export just the function.
Sure, by following this convention you will end up with more modules than usual, but if you think about it, this is not actually that different from many other languages. E.g., in Java it's conventional to put each class in a separate file, no matter how small the class is.
I have to mention though that far from most people in the community actually follow this convention. You can often see cryptic names used to work around this. Personally I don't find such an approach very clean and would rather recommend using modules.
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