Haskell函数检查两个值是否相同

时间:2015-05-11 19:22:43

标签: haskell

在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。我该怎么做?

1 个答案:

答案 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?中的一个解决方案会更好。