Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine whether a value is a function in Haskell

Is it possible to write a function isFunc :: a -> Bool to determine whether an arbitrary value is a function (of any kind) such that

foo :: Int -> Int
bar :: Char -> Char -> Char    

> isFunc foo
True
> isFunc bar
True
> isFunc 3
False
> isFunc 'a'
False

I'm using Data.Dynamic so I can't determine the type in advance.

like image 565
jhibberd Avatar asked Apr 21 '12 11:04

jhibberd


People also ask

How are function defined in Haskell?

The most basic way of defining a function in Haskell is to ``declare'' what it does. For example, we can write: double :: Int -> Int double n = 2*n. Here, the first line specifies the type of the function and the second line tells us how the output of double depends on its input.

How do you check variable type in Haskell?

Load the Haskell file containing the above code snippet with the :l command in GHCI. You can see the type for each variable with the :t command. Types are printed in the variable :: Type format.

How do you read a Haskell function?

In Haskell read function is used to deal with strings, if you want to parse any string to any particular type than we can use read function from the Haskell programming. In Haskell read function is the in built function, that means we do not require to include or install any dependency for it, we can use it directly.


2 Answers

What are you asking for and what you need to do with Data.Dynamic seem to be different things. You need to know the exact type of value before extracting it with fromDyn/fromDynamic. To determine whether Dynamic contains a function value you need to analyze TypeRep:

isFuncDynamic x = typeRepTyCon (dynTypeRep x) == typeRepTyCon (typeOf2 id)

(Forgive me if this is not the most concise implementation.)

like image 109
rkhayrov Avatar answered Sep 28 '22 00:09

rkhayrov


Parametricity says no. The only functions of type

a -> Bool

are constant functions.

However, with a bit of ad hoc polymorphism and a bit more chutzpah, you can do this:

{-# LANGUAGE OverlappingInstances, FlexibleInstances #-}

class Sick x where
  isFunc :: x -> Bool

instance Sick (a -> b) where
  isFunc _ = True

instance Sick x where
  isFunc _ = False

and then it looks like you have

*Sick> isFunc 3
False
*Sick> isFunc id
True

But it does seem like a peculiar thing to do. What use is the resulting Bool to you?

like image 26
pigworker Avatar answered Sep 28 '22 00:09

pigworker