Ambiguous types for collection keys

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Ambiguous types for collection keys

Scott Weeks
Hello everyone,

I've been banging my head against my desk a bit so I figured it's time
to ask for help :-)

I'm writing an application that persists data to disk. The hard stuff
is pretty much done (binary serialisation, etc...) The big stumbling
block is that I want users to be able to define their own schemas. This
means that the keys for a data store may be Integer, Strings, etc...

I have a BTreeIndex type:

data BTreeIndex a b = Branch { parentBT :: !BlockPtr,
                                keysBT   :: ![a],
                                kidsBT   :: ![BlockPtr] }
                     | Leaf   { parentBT :: !BlockPtr,
                                valsBT   :: !(LeafMap a b),
                                prevBT   :: !PrevLeaf,
                                nextBT   :: !NextLeaf }

type IdxPS       = BTreeIndex PackedString BlockPtr
type IdxInt      = BTreeIndex Integer BlockPtr


When a user queries I have to read the input from IO and then somehow
cast the key/index type without angering the type checker. If I omit
the following function I get the ominous "Ambiguous type variable a..."
error. If I use it I get a complaint that the checker was expecting an
Integer rather than a PackedString.

coerceIndex f (Schema _ SInt SPtr _) (r,hdl,o,hdr) = f
(r::IdxInt,hdl,o,hdr)
coerceIndex f (Schema _ SStr SPtr _) (r,hdl,o,hdr) = f
(r::IdxPS,hdl,o,hdr)

Where f is a curried select function (e.g. selectAll, selectByKey,
etc...) waiting for the final tuple containing the index and other
miscellanea that is needed to read the data.

I'm hopelessly lost and I assume that the many brilliant minds on this
list will chuckle, pat me on the head and tell me what I've been doing
wrong.

Thanks for your time guys,
Scott
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous types for collection keys

ihope
On 4/12/06, Scott Weeks <[hidden email]> wrote:

> Hello everyone,
>
> I've been banging my head against my desk a bit so I figured it's time
> to ask for help :-)
>
> When a user queries I have to read the input from IO and then somehow
> cast the key/index type without angering the type checker. If I omit
> the following function I get the ominous "Ambiguous type variable a..."
> error. If I use it I get a complaint that the checker was expecting an
> Integer rather than a PackedString.

Well, if you get an "ambiguous type variable" error, you probably (I
think) need to add some type annotations. For example:

class Foo a where
  foo :: a
  bar :: a -> String

Evaluating bar foo will result in an error, but bar (foo :: Integer)
will work just fine.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous types for collection keys

Scott Weeks


>
> Well, if you get an "ambiguous type variable" error, you probably (I
> think) need to add some type annotations. For example:
>
> class Foo a where
>   foo :: a
>   bar :: a -> String
>
> Evaluating bar foo will result in an error, but bar (foo :: Integer)
> will work just fine.
> ____________________

The problem is that I get  an incoming value which is a key of some
sort. There's no way of knowing what type that value is supposed to be
until I compare it with the schema from the above example. where I _am_
adding type annotations.

coerceIndex f (Schema _ SInt SPtr _) (r,hdl,o,hdr) = f
(r::IdxInt,hdl,o,hdr)
coerceIndex f (Schema _ SStr SPtr _) (r,hdl,o,hdr) = f
(r::IdxPS,hdl,o,hdr)


When I try to add type annotations I get a complaint from the
typechecker that says (In the case of the above example) Expected type:
Integer, Inferred Type: PackedString.

Is the alternative to write different "select" methods for each key
type (selectInt, selectPS, ...)? God I hope not, that would be a bit
scary.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous types for collection keys

Bugzilla from robdockins@fastmail.fm

On Apr 12, 2006, at 3:18 PM, Scott Weeks wrote:

>
>
>>
>> Well, if you get an "ambiguous type variable" error, you probably (I
>> think) need to add some type annotations. For example:
>>
>> class Foo a where
>>   foo :: a
>>   bar :: a -> String
>>
>> Evaluating bar foo will result in an error, but bar (foo :: Integer)
>> will work just fine.
>> ____________________
>
> The problem is that I get  an incoming value which is a key of some  
> sort. There's no way of knowing what type that value is supposed to  
> be until I compare it with the schema from the above example. where  
> I _am_ adding type annotations.
>
> coerceIndex f (Schema _ SInt SPtr _) (r,hdl,o,hdr) = f  
> (r::IdxInt,hdl,o,hdr)
> coerceIndex f (Schema _ SStr SPtr _) (r,hdl,o,hdr) = f  
> (r::IdxPS,hdl,o,hdr)
>
>
> When I try to add type annotations I get a complaint from the  
> typechecker that says (In the case of the above example) Expected  
> type: Integer, Inferred Type: PackedString.
>
> Is the alternative to write different "select" methods for each key  
> type (selectInt, selectPS, ...)? God I hope not, that would be a  
> bit scary.


I'm not 100% sure I understand your use case, but I think you might  
be able to crack this by using Data.Dynamic:

http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data- 
Dynamic.html




Speak softly and drive a Sherman tank.
Laugh hard; it's a long way to the bank.
           -- TMBG



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous types for collection keys

Brandon Moore
Robert Dockins wrote:

>
> On Apr 12, 2006, at 3:18 PM, Scott Weeks wrote:
>
>>
>>
>>>
>>> Well, if you get an "ambiguous type variable" error, you probably (I
>>> think) need to add some type annotations. For example:
>>>
>>> class Foo a where
>>>   foo :: a
>>>   bar :: a -> String
>>>
>>> Evaluating bar foo will result in an error, but bar (foo :: Integer)
>>> will work just fine.
>>> ____________________
>>
>>
>> The problem is that I get  an incoming value which is a key of some  
>> sort. There's no way of knowing what type that value is supposed to  
>> be until I compare it with the schema from the above example. where  I
>> _am_ adding type annotations.
>>
>> coerceIndex f (Schema _ SInt SPtr _) (r,hdl,o,hdr) = f  
>> (r::IdxInt,hdl,o,hdr)
>> coerceIndex f (Schema _ SStr SPtr _) (r,hdl,o,hdr) = f  
>> (r::IdxPS,hdl,o,hdr)
>>
>>
>> When I try to add type annotations I get a complaint from the  
>> typechecker that says (In the case of the above example) Expected  
>> type: Integer, Inferred Type: PackedString.
>>
>> Is the alternative to write different "select" methods for each key  
>> type (selectInt, selectPS, ...)? God I hope not, that would be a  bit
>> scary.
>
>
>
> I'm not 100% sure I understand your use case, but I think you might  be
> able to crack this by using Data.Dynamic:
>
> http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data- 
> Dynamic.html

Or carry an instance in along with a type parameter, using existentials
or GADT.

Brandon Moore
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous types for collection keys

Scott Weeks
>
> Or carry an instance in along with a type parameter, using
> existentials or GADT.
>
> Brandon Moore

Do you know of an example that would apply to my situation?

I think I neglected to state part of my problem. I am storing the root
nodes of btree indexes in a heterogeneous list using Typeable. When
they come out of the list they need to be unwrapped

I think this will clarify my situation because I've been doing a poor
job of explaining:

import Data.Dynamic

data Foo a = FVal a
              deriving (Show, Typeable)

type FooStr = Foo String
type FooInt = Foo Integer

main = do
   fooType <- getLine
   fooVal  <- getLine
   let foo   = toDyn (FVal fooVal)
       fs    = [foo]
       (f:_) = fs
       Just dynFoo = fromDynamic f
   dostuff dynFoo



dostuff :: (Show a) => Foo a -> IO ()
dostuff (FVal x) = print x


This fails with:

  Ambiguous type variable `a' in the constraints:
       `Typeable a'
        arising from use of `fromDynamic' at
/Users/weeksie/workspace/haskell/Main.hs:243:20-30
       `Show a'
        arising from use of `dostuff' at
/Users/weeksie/workspace/haskell/Main.hs:247:2-8
     Probable fix: add a type signature that fixes these type variable(s)


However, changing main:

main = do
   fooType <- getLine
   fooVal  <- getLine
   let foo   = toDyn (FVal fooVal)
       fs    = [foo]
       (f:_) = fs
       Just dynFoo = fromDynamic f
   if fooType == "str"
      then dostuff (dynFoo::FooStr)
      else dostuff (dynFoo::FooInt)


Fails with:

     Couldn't match `Integer' against `String'
       Expected type: FooInt
       Inferred type: FooStr
     In the expression: dynFoo :: FooInt
     In the first argument of `dostuff', namely `(dynFoo :: FooInt)'



I'm probably going about this in the wrong way. I'd love some advice on
how to either do it better or weave some Type Magic to achieve the same
effect.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous types for collection keys

Bugzilla from robdockins@fastmail.fm

On Apr 12, 2006, at 4:09 PM, Scott Weeks wrote:

>>
>> Or carry an instance in along with a type parameter, using  
>> existentials or GADT.
>>
>> Brandon Moore
>
> Do you know of an example that would apply to my situation?
>
> I think I neglected to state part of my problem. I am storing the  
> root nodes of btree indexes in a heterogeneous list using Typeable.  
> When they come out of the list they need to be unwrapped

> I think this will clarify my situation because I've been doing a  
> poor job of explaining:
>
> import Data.Dynamic
>
> data Foo a = FVal a
>              deriving (Show, Typeable)
>
> type FooStr = Foo String
> type FooInt = Foo Integer
>
> main = do
>   fooType <- getLine
>   fooVal  <- getLine
>   let foo   = toDyn (FVal fooVal)
>       fs    = [foo]
>       (f:_) = fs
>       Just dynFoo = fromDynamic f
>   dostuff dynFoo
>
>
>
> dostuff :: (Show a) => Foo a -> IO ()
> dostuff (FVal x) = print x
>
>
> This fails with:
>
>  Ambiguous type variable `a' in the constraints:
>       `Typeable a'
> arising from use of `fromDynamic' at /Users/weeksie/workspace/
> haskell/Main.hs:243:20-30
>       `Show a'
> arising from use of `dostuff' at /Users/weeksie/workspace/haskell/
> Main.hs:247:2-8
>     Probable fix: add a type signature that fixes these type  
> variable(s)
>
>
> However, changing main:
>
> main = do
>   fooType <- getLine
>   fooVal  <- getLine
>   let foo   = toDyn (FVal fooVal)
>       fs    = [foo]
>       (f:_) = fs
>       Just dynFoo = fromDynamic f
>   if fooType == "str"
>      then dostuff (dynFoo::FooStr)
>      else dostuff (dynFoo::FooInt)


You are trying to assign two distinct types to dynFoo; that's a no-
no.  You need to move the usage of the polymorphic function out of  
the let so that the use at each distinct type doesn't get unified.


{-# OPTIONS -fglasgow-exts #-}
import Data.Dynamic

data Foo a = FVal a
              deriving (Show, Typeable)

type FooStr = Foo String
type FooInt = Foo Integer

main = do
   fooType <- getLine
   fooVal  <- getLine
   let foo   = toDyn (FVal fooVal)
       fs    = [foo]
       (f:_) = fs
   if fooType == "str"
      then dostuff (fromDyn f undefined :: Foo String)
      else dostuff (fromDyn f undefined :: Foo Int)


dostuff :: (Show a) => Foo a -> IO ()
dostuff (FVal x) = print x



BTW, this little example always stuffs a string into the FVal, so  
trying to get anything else out will fail.



Rob Dockins

Speak softly and drive a Sherman tank.
Laugh hard; it's a long way to the bank.
           -- TMBG

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Ambiguous types for collection keys

Scott Weeks
>
> You are trying to assign two distinct types to dynFoo; that's a no-no.
>  You need to move the usage of the polymorphic function out of the let
> so that the use at each distinct type doesn't get unified.
>
>
> {-# OPTIONS -fglasgow-exts #-}
> import Data.Dynamic
>
> data Foo a = FVal a
>              deriving (Show, Typeable)
>
> type FooStr = Foo String
> type FooInt = Foo Integer
>
> main = do
>   fooType <- getLine
>   fooVal  <- getLine
>   let foo   = toDyn (FVal fooVal)
>       fs    = [foo]
>       (f:_) = fs
>   if fooType == "str"
>      then dostuff (fromDyn f undefined :: Foo String)
>      else dostuff (fromDyn f undefined :: Foo Int)
>
>
> dostuff :: (Show a) => Foo a -> IO ()
> dostuff (FVal x) = print x
>
>
>
> BTW, this little example always stuffs a string into the FVal, so
> trying to get anything else out will fail.


Thanks for the example it makes a bit of sense now, I really appreciate
you taking the time to help me on this.

Cheers,
Scott
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe