0
votes

I am new to Haskell.

I want to implement Ord class for a Custom Data type using Enum class.

It works fine if I implement Enum class and use the fromEnum function directly in the implementation of compare function required for Ord class.

But as Type Signatures and Type Level Constraints are for Readability and Documentation. I want to Specify the Ord instance of my custom data depends on Enum instance. When I write the below code it throws an error.

data DayOfWeek
  = Mon | Tue | Weds | Thu | Fri | Sat | Sun
  deriving (Eq, Show)    

instance Enum DayOfWeek => Ord DayOfWeek where
  compare a b = compare (fromEnum a) (fromEnum b)

instance Enum DayOfWeek where
  toEnum 1 = Mon
  toEnum 2 = Tue
  toEnum 3 = Weds
  toEnum 4 = Thu
  toEnum 5 = Fri
  toEnum 6 = Sat
  toEnum 7 = Sun

  fromEnum Mon = 1
  fromEnum Tue = 2
  fromEnum Weds = 3
  fromEnum Thu = 4
  fromEnum Fri = 5
  fromEnum Sat = 6
  fromEnum Sun = 7

Error:

* Non type-variable argument in the constraint: Enum DayOfWeek
  (Use FlexibleContexts to permit this)
* In the context: Enum DayOfWeek
  While checking an instance declaration
  In the instance declaration for `Ord DayOfWeek'

Can we write Constraints on Concrete Types

1
It would be simpler to just define the Enum instance first, then define the Ord instance. Also, there is a difference between needing an Enum instance and simply using it to define the Ord instance.chepner

1 Answers

5
votes

Your code compiles if we enable a pair of extensions, writing in the first line of the file:

{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}

Still, I think it's not worth it. I'd remove the context instead, since that is what most existing code does.

Further, I'm not sure about why do you think it's important to document the fact that one instance depends on the other. I would regard that as an implementation detail, hence something I'd like to hide from the user, rather than to point out.