在Haskell中,我们有函数(==) :: Eq a => a->a->Bool
,它适用于可以定义Eq
实例的大量数据类型。但是,有些类型没有合理的方法来定义Eq
的实例。一个例子是简单函数类型(a->b)
我正在寻找一个能告诉我两个值是否实际相同的函数 - 不等于但相同。
例如f(id,id)
==> True
f((+),(-))
=错误
澄清:
我不想知道两个函数是否做同样的事情。在一般情况下,这是不可能的。我想知道我是否已经回到了与我开始时相同的事情。让我举一个简单的例子:
data Foo = Foo (Foo->Foo) --contains a function so no Eq instance
x :: Foo
x = Foo id -- or for that matter Foo undefined
y :: Foo
y = Foo (const x)
a :: Foo
a = let (Foo fy) = y
in fy x
很明显,通过一次评估检查,a
将是x
。但是我们假设我不知道y中的函数但是我想测试我输入的Foo是否与我得到的相同 - 那就是fy x
给我x
。我该怎么做?
答案 0 :(得分:10)
Pointer equality in Haskell?中未提及的一种方法是reallyUnsafePtrEquality#
。顾名思义它可能是不可预测的,可能不应该使用,但看看ghc如何工作会很有趣。以下是如何在ghci中使用它:
> :set -package ghc-prim
> import GHC.Prim
> import GHC.Types
> isTrue# (reallyUnsafePtrEquality# id id)
True
> let a x = x + 2 :: Int
> isTrue# (reallyUnsafePtrEquality# a a)
True
> let b x = x + 2 :: Int
> isTrue# (reallyUnsafePtrEquality# a b)
False
如果函数不是单态的,则不起作用:
> let c x = x + 2
> isTrue# (reallyUnsafePtrEquality# c c)
False
更多例子:
> let d = c in isTrue# (reallyUnsafePtrEquality# d d)
False
> :set -XMonomorphismRestriction
> let d = c in isTrue# (reallyUnsafePtrEquality# d d)
True
如果将它们换成newtype,则可以比较多态类型:
> :set -XRankNTypes
> newtype X = X (forall a. Num a => a -> a)
> let d = X c
> isTrue# (reallyUnsafePtrEquality# d d)
True
应用任何东西都会使它们不相等
> isTrue# (reallyUnsafePtrEquality# (id ()) (id ()))
False
但是在使用优化进行编译时,这是True
。
希望这足以说服你,你想要的是一个坏主意。 Pointer equality in Haskell?中的一个解决方案会更好。