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 |
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 |
> > 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 |
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 |
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 |
>
> 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 |
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 |
>
> 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 |
Free forum by Nabble | Edit this page |