简体   繁体   中英

Flexible Function Declaration in Type Classes

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM