Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you mix record syntax with enumerations in Haskell data types?

I've written the following:

data Expression = Expression { lhs :: Int, rhs :: Expression } | Int

The problem is if I try to construct an Expression with just an int I get a partially applied function. What's the best way to fix this?

like image 742
northlane Avatar asked Dec 05 '25 03:12

northlane


1 Answers

Things to know up front:

  • every data constructor in a Haskell data declaration has its own name
  • data constructors live in an entirely separate namespace from type names

As the comments note, you are defining both a type named Expression and a data constructor named Expression. Because Haskell has separate namespaces for types and data constructors, the compiler is fine with this.

Also, you are creating a second data constructor named Int (which likewise doesn't conflict with the existing type named Int). This is probably not what you want, and is confusing to boot!

When you try to construct a value such as myExpr = Expression x y, you are using the first data constructor, not the type name or the second data constructor. The Expression data constructor expects two arguments: first an Int, then an Expression. That is why, if you just provide the first argument, you will get a partially applied function.


A corrected, more idiomatic version of your example might be:

data Expression = Assignment { lhs :: Int, rhs :: Expression }
                | Literal { value :: Int }

It is actually fairly common to see a data constructor with the same name as its type, if it is the only data constructor:

data Foo = Foo { unwrapFoo :: Int }
like image 60
comingstorm Avatar answered Dec 07 '25 18:12

comingstorm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!