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


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to