
Hey Chris, Thanks for you reply! So the thing is: I actually had an algebraic data type Action with several constructors, one for each Action. And I was deriving Read so there was no problem there. However, I want to be able to add and remove Actions more easily. That is why I transformed the algebraic data type into a typeclass. Similarly, if you think about Object Oriented programming, I want the flexibility of subclassing, where new subclasses can be added without a problem. The fact that parseAction only works on a finite number of Actions is not problematic for now! So, I would really appreciate your help in overcoming this problem! Best regards, José On 18-11-2012 03:08, Chris Wong wrote:
Hello José,
So, I have a typeclass "Action" which defines method "run":
class Action a where run :: a -> Int
(snipped)
Now, I want to parse either "A" or "B" from a String. I was thinking about something like this...
parseAction :: (Action a, Read a) => String -> a parseAction str | "(A " `isPrefixOf` str = (read :: String -> A) str | "(B " `isPrefixOf` str = (read :: String -> B) str
The problem is that when calling "parseAction" I get "ambiguous type constraints". How to implement a parse function for two distinct types that share the same typeclass "Action". Because after calling "parseAction" I don't whether "A" or "B" was returned: I only care that they are "Action" instances so I can call "run". The problem with your current type:
(Action a, Read a) => String -> a
is that it actually means:
For any type that implements Action and Read, I can convert a string to that type.
This is wrong because if a user of your module added another type C, your function wouldn't be able to handle it -- it only "knows" about A and B. That is what GHC is trying to tell you.
How you can solve this problem depends on what you're trying to do. If there is a finite number of actions, you can merge them into a single type and remove the type class altogether:
data Action = A Int | B Int deriving (Read, Show)
run :: Action -> Int run (A x) = x run (B x) = x
parse :: String -> Action parse = read
If you have a possibly unlimited number of possible actions, there are many approaches to this -- including, as Stephen said, existential types. However, it's hard to decide on a proper solution without knowing what you're actually trying to do.
Chris
Best regards, José
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- José António Branquinho de Oliveira Lopes Instituto Superior Técnico Technical University of Lisbon