在 GHC 中,有没有办法在运行时确定一个抽象值是否是一个函数?

Is there a way to determine at runtime, in GHC, whether an abstract value is a function?

我想知道是否有可能有一个功能(有点类似于dataToTag#)像:

isFunction# :: a -> Bool

或可能等效地:

isFunction# :: Any -> Bool

which returns True iff 作为参数传入的值在运行时是 a -> b 类型(或者,就此而言,a => b)类型 ab,或者一个 newtype 其基础类型是(所以它是 "sees through" newtypes,但当然不是 data),没有强迫它的论点。我自己在 GHC.Prim 中没有看到类似的东西,但我可能漏掉了一些东西,或者可能使用手动 CMM primop 或其他东西。

既然我想到了这个问题,我很好奇它本身的答案 (question Y),但我想到这个问题(问题 X)的最初原因是投诉通常会平息反对 seq 的是它通过观察 undefined\_ -> undefined 之间的差异打破了 eta 等价性,我想知道是否有可能制作 [=21] 的一个版本=] (myseq a = if isFunction# a then flip const a else seq a) 仍然是 "magically polymorphic"(有效 forall a),但只是单独保留函数。

不,肯定不是。不评估参数怎么知道?

但是为了直接解决你的问题 X,你提出的 myseq 比真正的 seq 更糟糕,因为它破坏了参数化。是myseq undefined :: b -> b底,还是身份?这取决于类型变量 a (undefined :: a) 是否使用函数类型实例化。

在 Haskell 中,当 a 根本没有出现在类型中时,您总是可以删除 forall a.,这要归功于参数化:a 的选择没关系。你的 myseq 会失去那个 属性.

这也是为什么如果不在运行时用预期类型注释值就无法实现 isFunction#isFunction# undefined 同样没有意义)。