I am trying to make a type class Expr, which represents a generic expression. An instance of this class is ExprT Supported expressions are literals, add, and multiply. Here is my code so far:
class Expr a where
lit :: Eq x => x -> a
add :: a -> a -> a
mul :: a -> a -> a
data ExprT = Lit Integer
| Add ExprT ExprT
| Mul ExprT ExprT
deriving (Show, Eq)
instance Expr ExprT where
lit = Lit
add = Add
mul = Mul
However, when I run this, I get the following error:
* Couldn't match type `x' with `Integer'
`x' is a rigid type variable bound by
the type signature for:
lit :: forall x. Eq x => x -> ExprT
......
My goal is to make different instances of Expr for Integers, Floats, and maybe even non-numerical types like Chars, but I am not sure how to get past this error.
Well your signature for lit
is very generic:
class Expr a where
lit ::
add :: a -> a -> a
mul :: a -> a -> a
Such signature says that your lit
will accept any sort of type x
for which Eq x
holds. So for ExprT
, one can pass an Integer
, Float
, String
, etc. an you will return an ExprT
. You probably do not want this.
You can define an extra parameter like:
{-# LANGUAGE #-}
class Expr a | where
lit :: -> a
add :: a -> a -> a
mul :: a -> a -> a
and then declare an instance of Expr
for ExprT
as:
instance Expr ExprT where
lit = Lit
add = Add
mul = Mul
An alternative might be to "lift" your ExprT
data type with a type parameter:
{-# LANGUAGE #-}
data ExprT a where
Lit :: Eq a => a -> ExprT a
Add :: ExprT x -> ExprT a -> ExprT a
Mul :: ExprT x -> ExprT a -> ExprT a
and thus define this as:
class Expr e where
lit :: Eq => -> e
add :: e -> e -> e
mul :: e -> e -> e
instance Expr ExprT where
lit = Lit
add = Add
mul = Mul
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.