wierd type-error of 2 different records with a field with same name

Viewed 42

I have the following data structure:

data Exp
  = Var String
  | Unary
    { exp :: Exp 
    , op :: UnaryOp}
  | Binary
    { left :: Exp
    , right :: Exp
    , op :: BinaryOp
    }

data UnaryOp = Not

data BinaryOp = And | Or | Impl | Equal

And I get the following error:

Constructors Binary and Unary give different types for field ‘op’

But I dont get why the different types for the op make a problem. They are in records of diffrent variants. They should be independent things shouldnt they ?

1 Answers

The record syntax is just a nice shorthand for defining functions that "extract" out that field. Normally, you'd write something along the lines of:

exp :: Exp -> Exp
exp (Unary e _) = e
exp _ = error "undefined for non-Unary thing"

In that case that two of the variants both have the same field, it becomes something like:

data Shape
  = Square { sides :: Int }
  | Triangle { sides :: Int }

------- same as ----------
sides :: Shape -> Int
sides (Square s) = s
sides (Triangle s) = s

However, if you have what you wrote, it's unclear what the return type of op should be. Should it have type Exp -> UnaryOp or Exp -> BinaryOp? It depends on what you actually give it. I suggest renaming one of them so that there's no confusion on what it should return.

Related