Problem on using class as type.

Hi, I have a function: post :: (ToJson p, FromJson q) => String -> String -> String -> Map.Map String p -> IO q Now I'd like to call it like: r <- post site token "user.addMedia" (Map.fromList [ ("users", users :: ToJson) , ("medias", medias :: ToJson) ]) So I got the problem. If I used things like "users :: ToJson", then class used as a type error occurred. But if I did not use them, since users and medias were actually different types, then fromList failed, required the type of medias the same with users. How to resolve the conflict? -- 竹密岂妨流水过 山高哪阻野云飞

What about "users :: ToJson a => a"? On Tue, Oct 4, 2011 at 12:42 AM, Magicloud Magiclouds < magicloud.magiclouds@gmail.com> wrote:
Hi, I have a function: post :: (ToJson p, FromJson q) => String -> String -> String -> Map.Map String p -> IO q Now I'd like to call it like: r <- post site token "user.addMedia" (Map.fromList [ ("users", users :: ToJson) , ("medias", medias :: ToJson) ]) So I got the problem. If I used things like "users :: ToJson", then class used as a type error occurred. But if I did not use them, since users and medias were actually different types, then fromList failed, required the type of medias the same with users.
How to resolve the conflict? -- 竹密岂妨流水过 山高哪阻野云飞
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Mon, Oct 03, 2011 at 09:42:59PM +0800, Magicloud Magiclouds wrote:
Hi, I have a function: post :: (ToJson p, FromJson q) => String -> String -> String -> Map.Map String p -> IO q Now I'd like to call it like: r <- post site token "user.addMedia" (Map.fromList [ ("users", users :: ToJson) , ("medias", medias :: ToJson) ]) So I got the problem. If I used things like "users :: ToJson", then class used as a type error occurred. But if I did not use them, since users and medias were actually different types, then fromList failed, required the type of medias the same with users.
If users and medias are different types, then you cannot put them in the same list. The ToJson class provides a method toJson :: ToJson a => a -> Json so presumably you need to call this method on users and medias, like ... ("users", toJson users) , ("medias", toJson medias) -Brent

On 10/03/2011 10:42 PM, Magicloud Magiclouds wrote:
Hi, I have a function: post :: (ToJson p, FromJson q) => String -> String -> String -> Map.Map String p -> IO q Now I'd like to call it like: r<- post site token "user.addMedia" (Map.fromList [ ("users", users :: ToJson) , ("medias", medias :: ToJson) ]) So I got the problem. If I used things like "users :: ToJson", then class used as a type error occurred. But if I did not use them, since users and medias were actually different types, then fromList failed, required the type of medias the same with users.
How to resolve the conflict?
If 'users' and 'medias' are actually of a general type (like "for all a with ToJson a, users describes a value of type a"), use Jesse's suggestion. Otherwise ("there is an a with ToJson a such that users describes a value of type a"), you might want to use existentials: {-# LANGUAGE ExistentialQuantification #-} data SomeToJson = forall a. (ToJson a) => SomeToJson a instance ToJson SomeToJson where toJson (SomeToJson x) = toJson x -- I guess your class looks like this? And then: r <- post site token "user.addMedia" $ Map.fromList [("users", SomeToJson users), ("medias", SomeToJson medias)] As a last remark, I needed this pattern exactly once, namely for dealing with rank 2 types in rendering functions using takusen. I can conclude that requiring it is often an indicator for a major design flaw in your program. In this case: Why not: -- assuming that there is an -- instance ToJson Json where toJson = id r <- post site token "user.addMedia" $ Map.fromList [("users", toJson users), ("medias", toJson medias)] Cheers!

Hi there,
I am using the "toJson = id" way, which doesn't seem to cause other problem.
Thank you.
On Mon, Oct 3, 2011 at 11:18 PM, Steffen Schuldenzucker
On 10/03/2011 10:42 PM, Magicloud Magiclouds wrote:
Hi, I have a function: post :: (ToJson p, FromJson q) => String -> String -> String -> Map.Map String p -> IO q Now I'd like to call it like: r<- post site token "user.addMedia" (Map.fromList [ ("users", users :: ToJson) , ("medias", medias :: ToJson) ]) So I got the problem. If I used things like "users :: ToJson", then class used as a type error occurred. But if I did not use them, since users and medias were actually different types, then fromList failed, required the type of medias the same with users.
How to resolve the conflict?
If 'users' and 'medias' are actually of a general type (like "for all a with ToJson a, users describes a value of type a"), use Jesse's suggestion. Otherwise ("there is an a with ToJson a such that users describes a value of type a"), you might want to use existentials:
{-# LANGUAGE ExistentialQuantification #-} data SomeToJson = forall a. (ToJson a) => SomeToJson a
instance ToJson SomeToJson where toJson (SomeToJson x) = toJson x -- I guess your class looks like this?
And then: r <- post site token "user.addMedia" $ Map.fromList [("users", SomeToJson users), ("medias", SomeToJson medias)]
As a last remark, I needed this pattern exactly once, namely for dealing with rank 2 types in rendering functions using takusen. I can conclude that requiring it is often an indicator for a major design flaw in your program. In this case:
Why not:
-- assuming that there is an -- instance ToJson Json where toJson = id r <- post site token "user.addMedia" $ Map.fromList [("users", toJson users), ("medias", toJson medias)]
Cheers!
-- 竹密岂妨流水过 山高哪阻野云飞
participants (4)
-
Brent Yorgey
-
Jesse Schalken
-
Magicloud Magiclouds
-
Steffen Schuldenzucker