
Hello all, I suppose the natural representation for a Table is a List of Tuples. Or more generally I'll probably end up with a type "Table a" where a stands for the Columns. I cannot figure out how to add a new Column to a Table. What would be the type of such an operation? If I just want to add an empty Column (which what an RDBMS would do), would I do something like this? addColumn :: ColumnDef -> Table a -> Table b But what is this ColumnDef? It would need to contain the name and type of the new column. To implement this operation I would have to somewehre add a column to something. But what is the type of this something. I don't see how I can add a component to a Tuple in a generic way, or can I? I browsed some code on Hackage and found code which uses Data.Proxy. It this the right direction? Or do I need to look at GADTs, or template haskell? Or am I overcomplicating things, and there is a true haskellish solution?

Hello, Have a look at vinyl (https://hackage.haskell.org/package/vinyl) and HList (https://hackage.haskell.org/package/HList), packages that provide extensible records. I haven't used HList, but I can attest vinyl is quite easy to use. You can also have a look at http://www.reddit.com/r/haskell/comments/32tdt6/functions_for_type_level_lis... for some discussion regarding implementation of relational databases in Haskell; I've linked to my (very) unfinished code there: http://hub.darcs.net/mjm/relational/browse/src/Data/Relational feel free to steal ideas :-P Best regards, Marcin Mrotek

On 04/26/2015 06:13 AM, martin wrote:
Hello all,
I suppose the natural representation for a Table is a List of Tuples. Or more generally I'll probably end up with a type "Table a" where a stands for the Columns.
I cannot figure out how to add a new Column to a Table. What would be the type of such an operation? If I just want to add an empty Column (which what an RDBMS would do), would I do something like this?
addColumn :: ColumnDef -> Table a -> Table b
But what is this ColumnDef? It would need to contain the name and type of the new column. To implement this operation I would have to somewehre add a column to something. But what is the type of this something. I don't see how I can add a component to a Tuple in a generic way, or can I?
type Person = ( Int, -- ID String, -- Name Int, -- Age Bool -- Evil bit ) type Place = ( Int, -- ID String, -- Name Double, -- Longitude Double, -- Latitude Double -- Elevation ) data Column = Person | Place type Table = [Column] addColumn :: Table -> Column -> Table addColumn table col = table ++ [col]

Am 04/26/2015 um 09:46 PM schrieb Michael Orlitzky:
On 04/26/2015 06:13 AM, martin wrote:
Hello all,
I suppose the natural representation for a Table is a List of Tuples. Or more generally I'll probably end up with a type "Table a" where a stands for the Columns.
I cannot figure out how to add a new Column to a Table. What would be the type of such an operation? If I just want to add an empty Column (which what an RDBMS would do), would I do something like this?
addColumn :: ColumnDef -> Table a -> Table b
But what is this ColumnDef? It would need to contain the name and type of the new column. To implement this operation I would have to somewehre add a column to something. But what is the type of this something. I don't see how I can add a component to a Tuple in a generic way, or can I?
type Person = ( Int, -- ID String, -- Name Int, -- Age Bool -- Evil bit )
type Place = ( Int, -- ID String, -- Name Double, -- Longitude Double, -- Latitude Double -- Elevation )
data Column = Person | Place
type Table = [Column]
addColumn :: Table -> Column -> Table addColumn table col = table ++ [col]
Aren't you adding a *row* to a Table which allows rows of multiple shapes? What I am looking for is an operation which adds a *column* to a regular table, i.e. one where all rows have the same shape. But I like your idea of adding an "Evil bit" to Persons.

On 04/27/2015 02:46 AM, martin wrote:
Aren't you adding a *row* to a Table which allows rows of multiple shapes? What I am looking for is an operation which adds a *column* to a regular table, i.e. one where all rows have the same shape.
Oh, shit =) Adding a column is a lot harder and does need some kind of "heterogenous list" library. To do it without one, you need something like, https://github.com/orlitzky/tuple/commit/8f6623b827f2192343c4fa4d520a4eb1730... That has one advantage: you can understand what it's doing. But it's not, uh, what's the word -- "aesthetically pleasing." My "prepend" is basically your "addColumn," and you can see that the type is, prepend :: a -> b -> c but that there's a functional dependency, a b -> c, b c -> a which basically means that the output tuple's type is going to depend on the input tuple's type and the type of the element that you're prepending to it. You can make this work on a table, too: type Table a = [a] addColumn :: Prep a b c => a -> Table b -> Table c addColumn col = map (prepend col) But if you know the type of the new (bigger) row at compile-time, what you probably want instead is fixed-vector-hetero. Then you can write, import qualified Data.Vector.HFixed as H ( cons ) ... addColumn col = map (H.cons col) That will work for any HVector row type, but you need to either specify or have the result type inferred. Otherwise you'll get an ambiguous type error. So this won't work: ghci> let p1 = (1,"mjo",9000,True) :: Person ghci> let t1 = [p1] :: Table Person ghci> addColumn "new" t1 But this would, ghci> addColumn "new" t1 :: Table (String, Int, String, Int, Bool) [("new",1,"mjo",9000,True)] If the result type can't be inferred, the tuple solution I mentioned earlier might be less annoying, but switching "prepend" to "append" is up to you!
participants (3)
-
Marcin Mrotek
-
martin
-
Michael Orlitzky