0
votes

So, I've been banging my head against the wall for at least an hour now. Here's my problem:

One of my functions returns [(Text, Text)].

Now I want to populate Document in Data.Bson using this list of tuples.

With the extension OverloadedStrings turned on, and with Data.Text imported as well as Data.Bson, I do (this part is edited from original post, which I pasted a debug version of the code which actually doesn't use the accumulator):

tuplesToBSON :: [(Text, Text)] -> Document
tuplesToBSON xs = L.foldr (\v acc -> merge [fst v =: snd v] acc) [] xs 

Where merge is from the Data.Bson package, as is =:.

No luck. It complains: Couldn't match expected type Label with actual type Text. (below is also an edit for clarity) If I try:

tuplesToBSON xs = L.foldr (\v acc -> merge [(fst v) =: (String (snd v))] acc ) [] xs

where this unfortunately named String is actually a constructor (I think...) from the Bson package for a data type called "Value". http://hackage.haskell.org/packages/archive/bson/0.2.1/doc/html/src/Data-Bson.html

This still doesn't work--but a different error message:

No instance for (Val Value) arising from a use of `=:'
Possible fix: add an instance declaration for (Val Value)
In the expression: (fst v) =: (String (snd v))
In the first argument of `merge', namely `[(fst v) =: (String (snd v))]'
In the expression: merge [(fst v) =: (String (snd v))] acc

as well as:

Couldn't match expected type `Label' with actual type `Text'
Expected type: [(Label, text-0.11.2.0:Data.Text.Internal.Text)] Actual type: [(Text, Text)]
In the third argument of `L.foldr', namely `xs'
In the expression: L.foldr (\ v acc -> merge [(fst v) =: (String (snd v))] acc) [] xs

I know that Value is a data type from the Bson package, but I really don't know what Val is.

===== START of now IRRELEVANT PORTION =====

And as one of the answers below pointed out, in the original post, I had :: String in my code "casting" a Text to a String as in the Prelude. I actually thought :: String was referring to the one mentioned in the Bson package, but I was completely wrong anyway, because (I think) String is actually a constructor.

I suspect somehow the GHC type inference is confused somehow, because the following works fine:

testDocument :: Document
testDocument = [(fst ("asdf", "awef") :: Label) =: ("asdf" :: String)]

Edit: This works but must be because Bson does some proper type handling automatically because after included the line import Prelude hiding (String) it gives me an error as it should.

So I've finally cleaned up the question. Sorry for the previous messy version--I was quite frustrated.

2
Incidentally, you're dropping the acc on the floor. Maybe you meant to use ((fst v) := (snd v)) : acc instead of just returning a 1-element list?Lily Ballard
oh yeah, that was actually still debug code :)Victor

2 Answers

0
votes

I think your problem isn't the Label, it's the b0. Looks like you're trying to assert that snd v is a String when it's not. Try using something like

tuplesToBSON xs = L.foldr (\acc v ->  [ ((fst v) :: Label) := (unpack (snd v) :: String)] ) [] xs

Although I'm not quite sure what all the inline type assertions are for. This is probably more readable as

tuplesToBSON xs = L.foldr (\acc v -> [(fst v) := (unpack (snd v0)]) [] xs
0
votes

First off, it isn't clear what you are trying to do. You aren't even using the accumulator (acc) so this is a degenerate traversal. You might as well say:

tuplesToBSON = (\v -> fst v =: snd v) . last

Another issue is your types are clearly contradictory. You say you're passing in a Text then inside the lambda you explicitly state you think the variable should be a String. You can't just add type annotations and think of them as a coerce operation, as you say in the question. The type of a variable must remain consistent and any coercion is done by an explicit function application (unpack in this case).

So lets assume that's just a mistaken use of foldr and we want to actually use the accumulator. Lets further assume you want the Text type and any use of String was just accidental.

The third issue is it seems you have your variables mixed up, in a foldr the second argument is the accumulator, not the first. So we should have:

tuplesToBSON = foldr (\v acc -> (fst v =: snd v) : acc) []

And this type checks fine. If the eta reduction and other clean-ups make it too hard for you to see the similarity to your code then consider this version:

tuplesToBSON xs = foldr (\v acc -> ((fst v :: Label) =: (snd v :: Text)) : acc ) [] xs