Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell lists of datatypes

Tags:

types

haskell

This is probably another easy Haskell question. If I have some "nested" data types, such as in this example code:

data Place = Country
           | State
           | City String
           deriving Show

data State = California
           | NewYork
           deriving Show

data Country = USA
             | Canada
             deriving Show

I can legally make a list such as [USA, Canada] of type [Country], or [California, NewYork] of type [State], or [City "a", City "b"] of type [Place].

What do I have to do to make a list such as [USA, NewYork]? NewYork is a State which is a Place, and USA is a Country which is a Place, but ghci sees USA so it assumes I am making a list of Countrys (and NewYork is a State, so the list fails).

I think I need some way to cast a Country or State to a Place, but I'm at a loss on how to accomplish this.

I'm trying to avoid throwing the data contained within State and Country into the Place type, which I know would make it work, but I've got a decent amount of real data that I'd rather not jumble up like that.

like image 436
Mark Rushakoff Avatar asked Jun 23 '09 14:06

Mark Rushakoff


People also ask

Is list a data type in Haskell?

Lists are an algebraic datatype of two constructors, although with special syntax, as described in Section 3.7.

Does Haskell have lists?

In Haskell, lists are a homogenous data structure. It stores several elements of the same type. That means that we can have a list of integers or a list of characters but we can't have a list that has a few integers and then a few characters.

What are types in Haskell?

In Haskell, types are how you describe the data your program will work with.


2 Answers

Here's a little more output that led me to figure out the problem:

*Main> [State, State]
[State,State]
*Main> :t State
State :: Place
*Main> :t NewYork
NewYork :: State

This seems to imply that the word "State" is a valid constructor for Place, and that the data State refers to a value of only California or NewYork.

If you change the program slightly, to:

data Place = Country Country
           | State State
           | City String
           deriving Show

data State = California
           | NewYork
           deriving Show

data Country = USA
             | Canada
             deriving Show

then you can make a list such as [Country USA, State NewYork] which is properly of type [Place]. Using the same word twice as in the first example does not "bind" the State type together in the way I had thought it would.

Of course, using the constructor State State is just a matter of preference, I could just as easily do AmericanState State within the Place type if I were so inclined.

like image 51
Mark Rushakoff Avatar answered Sep 22 '22 07:09

Mark Rushakoff


{-# LANGUAGE ExistentialQuantification #-}
data GenericPlace = forall a. Show a => GenericPlace a
places :: [GenericPlace]
places = [GenericPlace USA, GenericPlace NewYork]

See the GHC user guide # 7.4.4 Existentially quantified data constructors for some restrictions with this approach.


There's a in-depth study of making usable heterogeneous collections in Haskell.

Strongly typed heterogeneous collections

A heterogeneous collection is a datatype that is capable of storing data of different types, while providing operations for look-up, update, iteration, and others. There are various kinds of heterogeneous collections, differing in representation, invariants, and access operations. We describe HList --- a Haskell library for strongly typed heterogeneous collections including extensible records. We illustrate HList's benefits in the context of type-safe database access in Haskell. The HList library relies on common extensions of Haskell 98. Our exploration raises interesting issues regarding Haskell's type system, in particular, avoidance of overlapping instances, and reification of type equality and type unification.

like image 39
ephemient Avatar answered Sep 23 '22 07:09

ephemient