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

Haskell函数检查两个值是否相同,haskell,Haskell,在Haskell中,我们有一个函数==::Eq a=>a->a->Bool,这对于可以定义Eq实例的大量数据类型来说很好。然而,对于某些类型,没有合理的方法来定义Eq的实例。一个例子是简单的函数类型a->b 我正在寻找一个函数,该函数将告诉我两个值是否实际上相同-不相等,但相同 例如,fid,id==>True f+,-=False 澄清: 我不想知道两个函数是否做相同的事情。在一般情况下不可能这样做。我想知道我是不是回到了我开始做的事情。让我举一个简单的例子: data Foo = Foo (

在Haskell中,我们有一个函数==::Eq a=>a->a->Bool,这对于可以定义Eq实例的大量数据类型来说很好。然而,对于某些类型,没有合理的方法来定义Eq的实例。一个例子是简单的函数类型a->b

我正在寻找一个函数,该函数将告诉我两个值是否实际上相同-不相等,但相同

例如,fid,id==>True f+,-=False

澄清:

我不想知道两个函数是否做相同的事情。在一般情况下不可能这样做。我想知道我是不是回到了我开始做的事情。让我举一个简单的例子:

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。如何做到这一点?

中没有提到的一种方法是。顾名思义,它可能是不可预测的,可能不应该使用,但看看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
如果将多态类型包装为新类型,则可以对其进行比较:

> :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
但当使用优化进行编译时,这是正确的


希望这足以让你相信你想要的是个坏主意。中的一种解决方案会更好。

中没有提到的一种方法是。顾名思义,它可能是不可预测的,可能不应该使用,但看看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
如果将多态类型包装为新类型,则可以对其进行比较:

> :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
但当使用优化进行编译时,这是正确的


希望这足以让你相信你想要的是个坏主意。中的一个解决方案会更好。

可能与此问题相同?我几乎可以肯定你实际上并不想要这个。纯函数式编程中的值没有OOP对象那样的标识。在Haskell中比较两个函数几乎是不可能的。例如,Control.Applicative。和Control.Monad.ap几乎相同,但由于其类型的不同而无法比较。您希望f\x->x+x\x->2*x的结果是什么?可能与此问题相同?我几乎可以肯定你实际上并不想要这个。纯函数式编程中的值没有OOP对象那样的标识。在Haskell中比较两个函数几乎是不可能的。例如,Control.Applicative。和Control.Monad.ap几乎相同,但由于它们的类型不同而不可比较。您希望f\x->x+x\x->2*x的结果是什么?@Sibi对,我的理解是c::Num a=>a->a,a根据ghci的默认规则默认为整数,因为它需要某种类型。这意味着c在每个站点都被克隆,因此它们有不同的指针值。另一方面,id不需要选择特定的类型,所以它指向相同的东西。@Sibi对,我的理解是c::Num a=>a->a,a根据ghci的默认规则默认为整数,因为它需要某种类型。这意味着c在每个站点都被克隆,因此它们有不同的指针值。另一方面,id不需要选择特定的类型,所以它指向同一个对象。