Derive Eq and Show for type alias in Haskell

大憨熊 提交于 2019-12-19 04:14:11

问题


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?


回答1:


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...




回答2:


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>"


来源:https://stackoverflow.com/questions/15015698/derive-eq-and-show-for-type-alias-in-haskell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!