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

I wonder if it is possible to have a function (somewhat similar to dataToTag# ), for example:

 isFunction# :: a -> Bool 

or probably equivalent to:

 isFunction# :: Any -> Bool 

which returns True if the value passed as an argument is of type a -> b (or, for that matter, a => b ) at run time for some types a and b , or newtype , whose base type (therefore it is " sees " newtype s, but certainly not data ), without forcing its argument. I have not seen anything like this in GHC.Prim myself, but I may have missed something, or perhaps it is possible using the manual CMM primitive or something like that.

Now that I have been asked a question, I am curious to answer myself ( question Y ), but the original reason I came up with this (question X) is that the complaint usually aligns with seq because it violates eta equivalence, allowing observe the difference between undefined and \_ -> undefined , and I was wondering if it is possible to make a version of seq ( myseq a = if isFunction# a then flip const a else seq a ), which is still "magically polymorphic" (works forall a ) but just leaves the functions alone.

+6
source share
1 answer

No, of course not. How could he know without appreciating the argument?

But for a direct answer to your question X, your suggested myseq worse than the real seq , since it violates parametricity. Is myseq undefined :: b -> b lower or private? It depends on whether a variable of type a ( undefined :: a ) was created with the type of the function or not.

In Haskell, you can always discard forall a. when a does not appear in the type at all, due to parametricity: the choice of a cannot matter. Your myseq will lose this property.

This is why you could not implement isFunction# without annotating the values โ€‹โ€‹at run time with their supposed types ( isFunction# undefined also makes no sense).

+4
source

All Articles