在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)