Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Derive Eq and Show for type alias in Haskell

I've the following type alias

data    Bindable  = Const Value 
                      | Variable Location
                    | Func Function
                    | Proc
              deriving (Eq, Show)                                   

type Function = Argument -> Store -> Value

but the compiler gives me an error

No instance for (Show Function)
arising from the 'deriving' clause of a data type declaration
Possible fix:
add an instance declaration for (Show Function)
or use a standalone 'deriving instance' declaration,
   so you can specify the instance context yourself
When deriving the instance for (Show Bindable)

Can I define Show & Eq for Function? If not then what would be the solution? Should I define Eq and Show to Argument, Store and Value?

like image 938
K'' Avatar asked Dec 04 '25 05:12

K''


2 Answers

Type class instances may only be defined for "real" types, as defined by a data or newtype declaration. A type declaration is a "fake" type—just an abbreviation for a longer type.

But that's just problem #1 in this case. Problem #2 is that even if you do this...

newtype Function = Function (Argument -> Store -> Value)

...there might still be no truly useful Show instance for Function. How do turn a function into a string? There are two strategies. First, the "just give up" strategy:

instance Show Function where
    show _ = "<some Function, no clue what it does>"

Second, the "canonical example" strategy, where you apply the Function to some canonical Argument and Store and show these together with the Value result:

instance Show Function where
    show (Function fn) = "Function: " 
                      ++ show defaultArgument 
                      ++ " -> " 
                      ++ show defaultStore
                      ++ " -> " 
                      ++ show (fn defaultArgument defaultStore)

The idea here is to display the Function as one particular argument/value mapping of it that might help you identify it more precisely than just using the same constant string for all of them. Whether this helps or not depends on what your functions do.

But now we have problem #3: neither of these obeys the intent/contract of the Show and Read classes, which is that read (show x) is equivalent to x. (People do often ignore this intent, however, just because they want to print something and Show is the quickest ticket. So much that, as Thomas DuBuisson points out, there's a standard module Text.Show.Functions that implements the "just give up" strategy.)

As for the Eq class, the answer is that it's just impossible in general to compare two functions for equality. (If I recall correctly, it's equivalent to solving the Halting Problem, but don't quote me on that.) If your solution requires you to compare functions for equality, you need a new solution...

like image 77
Luis Casillas Avatar answered Dec 07 '25 00:12

Luis Casillas


Just import Text.Show.Functions. Your type is just an alias, the error message is saying it can't find an instance of Show for (->), but an instance is available in that module.

Prelude> import Text.Show.Functions
Prelude Text.Show.Functions> show (+1)
"<function>"
like image 28
Thomas M. DuBuisson Avatar answered Dec 07 '25 00:12

Thomas M. DuBuisson