Skip to content

Much shorter instancing/generics-deriving syntax #3426

@jnbooth

Description

@jnbooth

This Haskell code is quite readable:

data SomethingA = Alice | Alfred | Alex deriving (Eq, Ord, Show, Bounded, Enum) 
data SomethingB = Bob | Bart            deriving (Eq, Ord, Show, Bounded, Enum) 
data SomethingC = Carol | Candice       deriving (Eq, Ord, Show, Bounded, Enum)
data SomethingD = David | Donald        deriving (Eq, Ord, Show, Bounded, Enum)

The equivalent PureScript code is basically unreadable, not to mention painful to write:

data SomethingA = Alice | Alfred | Alex
data SomethingB = Bob | Blart
data SomethingC = Carol | Candice
data SomethingD = David | Donald
derive instance _0_Generic SomethingA _ 
derive instance _1_Eq SomethingA 
derive instance _2_Ord SomethingA 
instance _3_Show SomethingA where
   show = genericShow 
instance _4_Enum SomethingA where
   succ = genericSucc
   pred = genericPred 
instance _5_Bounded SomethingA where
   top = genericTop
   bottom = genericBottom 
instance _6_BoundedEnum SomethingA where
   cardinality = genericCardinality
   toEnum = genericToEnum
   fromEnum = genericFromEnum 
derive instance _7_Generic SomethingB _ 
derive instance _8_Eq SomethingB 
derive instance _9_Ord SomethingB 
instance _10_Show SomethingB where
   show = genericShow 
instance _11_Enum SomethingB where
   succ = genericSucc
   pred = genericPred 
instance _12_Bounded SomethingB where
   top = genericTop
   bottom = genericBottom 
instance _13_BoundedEnum SomethingB where
   cardinality = genericCardinality
   toEnum = genericToEnum
   fromEnum = genericFromEnum 
derive instance _14_Generic SomethingC _ 
derive instance _15_Eq SomethingC
derive instance _16_Ord SomethingC 
instance _17_Show SomethingC where
   show = genericShow 
instance _18_Enum SomethingC where
   succ = genericSucc
   pred = genericPred 
instance _19_Bounded SomethingC where
   top = genericTop
   bottom = genericBottom 
instance _20_BoundedEnum SomethingC where
   cardinality = genericCardinality
   toEnum = genericToEnum
   fromEnum = genericFromEnum 
derive instance _21_Generic SomethingD _ 
derive instance _22_Eq SomethingD 
derive instance _23_Ord SomethingD 
instance _24_Show SomethingD where
   show = genericShow 
instance _25_Enum SomethingD where
   succ = genericSucc
   pred = genericPred 
instance _26_Bounded SomethingD where
   top = genericTop
   bottom = genericBottom 
instance _27_BoundedEnum SomethingD where
   cardinality = genericCardinality
   toEnum = genericToEnum
   fromEnum = genericFromEnum 

On top of the horrendous code bloat, twenty-eight useless instance names.

A few ideas:

  • Instance names could be cut out. I know this has been brought up before and decided against, with FFI as the excuse, but it would be the simplest solution so I figure I might as well mention it. Personally, I can't imagine more than a tiny fraction of instances are written with the intention of calling them from JavaScript. Perhaps there could be some kind of manual syntax for those use cases, something like foreign export eqFoo :: Eq Foo or something? I don't really want to worry about writing code for JavaScript in PureScript any more than I want to worry about writing code for C in Haskell.

  • Bounded could be derivable, along with Enum if the library is being used. This would at least cut down some of those lines.

  • Unsure of the specifics, but Generic might be allowed to define something along the lines of

deriveable Generic a _ :: BoundedEnum a where
    cardinality = genericCardinality
    toEnum = genericToEnum
    fromEnum = genericFromEnum

that could then be used for

derive instance boundedEnumFoo :: BoundedEnum Foo

EDIT: I guess this is really about giving an "opt-in" version of default method implementations, where you have to specify that you're going to borrow the defaults, in case that's less of an ordeal to add. If default method implementations were added, that would be even better.

  • At very least, some kind of deriving shorthand along the lines of:
data Foo = Foo deriving (Eq eqFoo, Show showFoo, Ord ordFoo, Generic genericFoo)

as an equivalent to

data Foo = Foo
derive instance eqFoo :: Eq Foo
derive instance showFoo :: Show Foo
derive instance ordFoo :: Ord Foo
derive instance genericFoo :: Generic Foo _

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions