
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!