
Hi Romildo, On Wed, May 2, 2012 at 3:08 PM, j.romildo wrote:
You are right in the sense that I cannot mix Expr Bool and Expr Double in a (O op l r) expression.
But the parser should be able to parse any form of expressions. So I rewrite my program to take this into account.
The new versions still does not compile:
Expr.hs:27:23: Couldn't match expected type `Double' with actual type `Bool' Expected type: ParsecT String () Data.Functor.Identity.Identity (Expr Double) Actual type: ParsecT String () Data.Functor.Identity.Identity (Expr Bool) In the first argument of `(<|>)', namely `pBool' In the second argument of `(<|>)', namely `pBool <|> pEqual'
From this, we see that the same type parameters to ParsecT are used in the two argument types as well as the result type. We also see that (<|>) is a right-associative infix operator. So, this means the offending line could be parenthesized as pArit <|> (pBool <|> pEqual), which fits the second
You appear to still be having the same problem. Perhaps this because you don't quite understand the type error? Let me help you dissect it. Since this is a type error, I'm not going to assume anything about what should or should not work. I'll only look at the types. First, let's comment out the offending line, so that your file type-checks: Line 27: -- pExpr = pArit <|> pBool <|> pEqual Next, let's look at each of the components relevant to the type error. The first mentioned is (<|>). In GHCi, we can find out more information about that: *Expr> :i (<|>) (<|>) :: ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a -- Defined in Text.Parsec.Prim infixr 1 <|> part of the type error, pBool <|> pEqual. Looking at the types of those, we see: *Expr> :t pBool pBool :: ParsecT String () Data.Functor.Identity.Identity (Expr Bool) *Expr> :t pEqual pEqual :: ParsecT String () Data.Functor.Identity.Identity (Expr Double) As we saw with the type of (<|>), these two types should be the "same" (as in unifiable). However, they are not, because the two type arguments to the Expr GADT differ: Bool in one case and Double in the other. GHC cannot "match" (unify) these types. Now, to the goal of your project: You say that the parser "should be able to parse any form of expressions," but since you are using a GADT with the expected expression types in the result index of each constructor, you can only define parsers that each parse an expression of a single type. That is, you can have a parser for Expr Bool and a parser for Expr Double, but these parsers can not be alternatives of another Expr and still have a valid type. This is, of course, the reason for using the type index as it is: you don't want Bool where you expect Double and vice versa. As a general comment, you may want to consider simplifying your goal to parsing only expressions of type Double. Then, what happens to your Bool constructors? Well, you could drop them, or you could extend your GADT with an "if" constructor that takes a boolean condition with Double alternatives. Regards, Sean