2

我有以下类型别名

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

type Function = Argument -> Store -> Value

但是编译器给了我一个错误

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)

我可以为函数定义 Show & Eq 吗?如果没有,那么解决方案是什么?我应该将 Eq 和 Show 定义为 Argument、Store 和 Value 吗?

4

2 回答 2

6

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

于 2013-02-22T02:19:10.263 回答
5

只需导入Text.Show.Functions. 你type只是一个别名,错误消息说它找不到 Show for(->)的实例,但该模块中有一个实例可用。

Prelude> import Text.Show.Functions
Prelude Text.Show.Functions> show (+1)
"<function>"
于 2013-02-22T02:12:48.000 回答