[Haskell-cafe] Parsing different types, same typeclass
chrisyco+haskell-cafe at gmail.com
Sun Nov 18 03:08:56 CET 2012
> So, I have a typeclass "Action" which defines method "run":
> class Action a where
> run :: a -> Int
> 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.
> Best regards,
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
More information about the Haskell-Cafe