Reputation: 586
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.
Upvotes: 0
Views: 1162
Reputation: 64740
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
Upvotes: 0
Reputation: 185671
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
Upvotes: 0