
Hello all, It seems this message was lost somehow, so i'm trying to send it again ....sorry if it comes up twice on the list ! I have this class which gives a common interface to (UniqueIndex a k) and (MultiIndex a k) : class (Show a, Key_ k) => Index_ i a k | i -> k, k -> a where buildKey :: (a -> k) insertIndex :: Id -> a -> i -> Maybe i deleteIndex :: Id -> a -> i -> i updateIndex :: Id -> a -> a -> i -> Maybe i updateIndex id oldItem newItem index = insertIndex id newItem $ deleteIndex id oldItem index Now i need to have these indexes in a list, so i declared that type : data DbIndex = forall a k i. (Show a, Key_ k, Index_ i a k) => DbIndex i Up to this point everything is fine, I can create concrete Indexes and put these different index types in the same list, after wrapping them in a DbIndex. But i don't seem to find a way to get out of this DbIndex type to actually work on the enclosed index. for instance, this doesn't work: liftDbIndex (DbIndex index) fun = DbIndex (fun index) this doesn't work either : dbIndexBuildKey (DbIndex index) value = (buildKey index) value How can i access the enclosed concrete index, via its Index_ class ? Maybe am I totally on the wrong track ? Thanks in advance, Sacha

Phlex schrieb:
I have this class which gives a common interface to (UniqueIndex a k) and (MultiIndex a k) :
I do not understand this
class (Show a, Key_ k) => Index_ i a k | i -> k, k -> a where buildKey :: (a -> k)
this method "buildKey" is not sufficient to derive the type "i" in an application ("i" determines "k" but not vice versa) [...]
Now i need to have these indexes in a list, so i declared that type :
data DbIndex = forall a k i. (Show a, Key_ k, Index_ i a k) => DbIndex i
data DbIndex = forall a k i. (Index_ i a k) => DbIndex i should do as well.
for instance, this doesn't work: liftDbIndex (DbIndex index) fun = DbIndex (fun index)
you can apply only a method of Index_ to index.
this doesn't work either : dbIndexBuildKey (DbIndex index) value = (buildKey index) value
buildKey's type is not sufficient (see above)
How can i access the enclosed concrete index, via its Index_ class ?
Add corresponding methods to the class. (Alternatively or additionally store an index as a dynamic value.) HTH Christian

On Fri, Jun 08, 2007 at 05:23:23PM +0200, Phlex wrote:
But i don't seem to find a way to get out of this DbIndex type to actually work on the enclosed index.
for instance, this doesn't work: liftDbIndex (DbIndex index) fun = DbIndex (fun index)
The compiler probably can't infer higher-ranker types, so you have to write you type signature explicitly. Try: liftDbIndex :: Index_ i2 a2 k2 => (forall a1 k1 i1. Index_ i1 a1 k1 => i1 -> i2) -> DbIndex -> DbIndex Best regards Tomek

On Fri, Jun 08, 2007 at 07:49:20PM +0200, Tomasz Zielonka wrote:
On Fri, Jun 08, 2007 at 05:23:23PM +0200, Phlex wrote:
But i don't seem to find a way to get out of this DbIndex type to actually work on the enclosed index.
for instance, this doesn't work: liftDbIndex (DbIndex index) fun = DbIndex (fun index)
The compiler probably can't infer higher-ranker types, so you have to write you type signature explicitly. Try:
liftDbIndex :: Index_ i2 a2 k2 => (forall a1 k1 i1. Index_ i1 a1 k1 => i1 -> i2) -> DbIndex -> DbIndex
Now I think that this type signature will be too restrictive. Ideally, i2, a2 and k2 would be existentially quantified, like liftDbIndex :: (forall a1 k1 i1. Index_ i1 a1 k1 => i1 -> (exists. Index_ i2 a2 k2 => i2)) -> DbIndex -> DbIndex AFAIK such type isn't supported by any Haskell compiler, so we have to use the existential quantification from DbIndex: liftDbIndex :: (forall a1 k1 i1. Index_ i1 a1 k1 => i1 -> DbIndex) -> DbIndex -> DbIndex liftDbIndex f (DbIndex i) = f i Best regards Tomek

Thanks to both Christian and Tomasz. This whole thing seems a bit too hard for the intended purpose. After much tries and errors, I think i'll go for closures returning DbIndex items. Something like this : uniqueIndex bkf datas = DbIndex{dbiInsertIndex=insertIndex, {- more methods -}} where index = UniqueIndex bkf datas insertIndex id item = do newIndex <- uniqueIndexInsert item index return $ uniqueIndex bkf $ uiItems newIndex -- more functions multiIndex bkf datas = DbIndex{dbiInsertIndex=insertIndex, {- more methods -}} where index = MultiIndex bkf datas insertIndex id item = do newIndex <- multiIndexInsert id item index return $ multiIndex bkf $ miItems newIndex -- more functions This keeps the definitions related to each index type close together, and allows for extention by adding new index types later on. Actually I don't even need the MultiIndex and UniqueIndex types anymore, making the code even shorter. Thanks for your time, Sacha Tomasz Zielonka wrote:
On Fri, Jun 08, 2007 at 07:49:20PM +0200, Tomasz Zielonka wrote:
On Fri, Jun 08, 2007 at 05:23:23PM +0200, Phlex wrote:
But i don't seem to find a way to get out of this DbIndex type to actually work on the enclosed index.
for instance, this doesn't work: liftDbIndex (DbIndex index) fun = DbIndex (fun index)
The compiler probably can't infer higher-ranker types, so you have to write you type signature explicitly. Try:
liftDbIndex :: Index_ i2 a2 k2 => (forall a1 k1 i1. Index_ i1 a1 k1 => i1 -> i2) -> DbIndex -> DbIndex
Now I think that this type signature will be too restrictive. Ideally, i2, a2 and k2 would be existentially quantified, like
liftDbIndex :: (forall a1 k1 i1. Index_ i1 a1 k1 => i1 -> (exists. Index_ i2 a2 k2 => i2)) -> DbIndex -> DbIndex
AFAIK such type isn't supported by any Haskell compiler, so we have to use the existential quantification from DbIndex:
liftDbIndex :: (forall a1 k1 i1. Index_ i1 a1 k1 => i1 -> DbIndex) -> DbIndex -> DbIndex liftDbIndex f (DbIndex i) = f i
Best regards Tomek

Just to keep you updated, Ok so the design was bad ... a table of elements 'a' will have indexes that hold elements of the same type 'a' so the list of indexes can be [dbIndex a].. There's was still one polymorphism issue : data DbIndex a = DbIndex {dbiInsert :: Row a -> Maybe (DbIndex a), dbiDelete :: Row a -> DbIndex a, dbiFindWithKey :: Dynamic -> Maybe [Row a]} indexDelete DbIndex{dbiDelete=delete} row = delete row indexInsert DbIndex{dbiInsert=insert} row = insert row findWithKey :: forall a k. (Typeable k) => (DbIndex a) -> k -> Maybe [Row a] findWithKey DbIndex{dbiFindWithKey=find} key = find $ toDyn key As far as i understand it, there is absolutely no way for the key in findWithKey to be fully typed while still having the indexes in the same list, so i took the given advice and used dynamics. I guess this is poor style but it does the job ! Thanks again Sacha
participants (3)
-
Christian Maeder
-
Phlex
-
Tomasz Zielonka