在Haskell中,我们有一个函数(==) :: Eq a => a->a->Bool,它适用于Eq可以定义实例的大量数据类型.但是,有些类型没有合理的方法来定义实例Eq.一个例子是简单的函数类型(a->b)
我正在寻找一个函数,告诉我两个值是否实际相同 - 不相等但相同.
例如f(id,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
Run Code Online (Sandbox Code Playgroud)
很明显,通过检查一旦评估,a将是x.但是我们假设我不知道y中的函数但我想测试我放入的Foo是否与我回来的相同 - 这确实fy x给了我x.我该怎么做呢?
cch*_*ers 10
在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
Run Code Online (Sandbox Code Playgroud)
如果函数不是单态的,则不起作用:
> let c x = x + 2
> isTrue# (reallyUnsafePtrEquality# c c)
False
Run Code Online (Sandbox Code Playgroud)
更多例子:
> let d = c in isTrue# (reallyUnsafePtrEquality# d d)
False
> :set -XMonomorphismRestriction
> let d = c in isTrue# (reallyUnsafePtrEquality# d d)
True
Run Code Online (Sandbox Code Playgroud)
如果将它们包装在newtype中,则可以比较多态类型:
> :set -XRankNTypes
> newtype X = X (forall a. Num a => a -> a)
> let d = X c
> isTrue# (reallyUnsafePtrEquality# d d)
True
Run Code Online (Sandbox Code Playgroud)
应用任何东西都会使它们不相等
> isTrue# (reallyUnsafePtrEquality# (id ()) (id ()))
False
Run Code Online (Sandbox Code Playgroud)
但是在使用优化进行编译时,这是True.
希望这足以说服你,你想要的是一个坏主意.Haskell中指针相等的解决方案之一?会更好.