在Haskell中为类型别名派生Eq和Show

在Haskell中为类型别名派生Eq和Show,haskell,functional-programming,typeclass,Haskell,Functional Programming,Typeclass,我有以下类型的别名 data Bindable = Const Value | Variable Location | Func Function | Proc deriving (Eq, Show) type Function = Argument -> S

我有以下类型的别名

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 to参数、存储和值吗?

只需导入
Text.Show.Functions
。您的
类型
只是一个别名,错误消息是无法找到
(>)
的Show实例,但该模块中有一个实例可用

Prelude> import Text.Show.Functions
Prelude Text.Show.Functions> show (+1)
"<function>"
Prelude>import Text.Show.Functions
序曲文本.Show.Functions>Show(+1)
""

类型类实例只能为“真实”类型定义,如
数据
newtype
声明所定义。
类型
声明是“假”类型,只是较长类型的缩写

但在这种情况下,这只是问题1。问题2是即使你这么做了

newtype Function = Function (Argument -> Store -> Value)
…对于
函数
,可能仍然没有真正有用的
显示
实例。如何将函数转换为字符串?有两种策略。首先,“放弃”战略:

instance Show Function where
    show _ = "<some Function, no clue what it does>"
这里的想法是将
函数
显示为它的一个特定参数/值映射,这可能有助于您更精确地识别它,而不仅仅是对所有函数使用相同的常量字符串。这是否有用取决于函数的功能

但现在我们有问题了#3:它们都不符合
Show
Read
类的意图/契约,也就是说
Read(Show x)
等同于
x
。(然而,人们常常忽略这一意图,仅仅因为他们想打印一些东西,
Show
是最快的选择。正如Thomas DuBuisson指出的那样,有一个标准的模块
Text.Show.Functions
实现了“放弃”策略。)


至于
Eq
类,答案是通常不可能比较两个函数是否相等。(如果我没记错的话,这相当于解决停止问题,但不要引用我的话。)如果您的解决方案要求您比较函数是否相等,您需要一个新的解决方案…

Thomas感谢您的快速帮助!它解决了这个问题。我应该为Eq导入什么?您必须编写自己的实例(根据需要默认为True或False)<代码>实例Eq函数,其中判断两个程序是否存在等价关系与解决停止问题一样困难。你必须知道一个函数是否停止,才能知道它是相等的!或者,
solveHalting f=(\y->seq(fx)y)==id
。我们知道,图灵证明不可能存在解Halting,所以没有函数的例子。是的,我理解你对Show的看法,它对我来说是完全有意义的。对于Eq,问题是我必须使Bindable能够导出Eq,因为我需要它作为其他函数的值和位置。虽然对于函数和过程我不需要它,但我也必须使它们成为可绑定的。你看到我的问题了吗?也许你可以重新定义
函数
来包含一个函数名,然后进行比较?取决于你的用例。@MikeHartl:问题是:平等意味着什么?最强的响应是
x==y
当且仅当对于所有
f
fx==fy
。用名称定义相等的问题是,即使你注意不要给两个不相等的函数赋予相同的名称,你也不能让两个相等的函数得到相同的名称。我能看到的唯一方法是,如果您的函数是从某个配方类型“编译”而来的,并且可以比较其相等性,那么“配方->函数转换”将保留配方相等性。(我想补充一句,这是一项非常好的技术。)
instance Show Function where
    show (Function fn) = "Function: " 
                      ++ show defaultArgument 
                      ++ " -> " 
                      ++ show defaultStore
                      ++ " -> " 
                      ++ show (fn defaultArgument defaultStore)