Function to display the function name

Is it possible in Haskell to implement a function that returns its own function name?

Possible type may be (a -> b) -> String.

+5
source share
4 answers

Do you need a function that takes a function argument and returns the name of a definition site variable that matches the name of this function?

This is not possible without metaprogramming, which is usually a sign that you are doing something wrong :). But assuming you havenโ€™t done this, one way to achieve something in the right direction is Template Haskell , which can get unique names (as the compiler calls things). For instance.

Prelude Language.Haskell.TH> :set -XTemplateHaskell
Prelude Language.Haskell.TH> let f x y = x + y
Prelude Language.Haskell.TH> $( stringE . show =<< reify 'f )

     "VarI f_1627394057
                (ForallT [PlainTV a_1627394063]
                         [ClassP GHC.Num.Num [VarT a_1627394063]]
                              (AppT (AppT ArrowT (VarT a_1627394063)) 
                                    (AppT (AppT ArrowT (VarT a_1627394063)) 
                                         (VarT a_1627394063)))) 
                         Nothing (Fixity 9 InfixL)"

. , , ( 'f), f.

, , -, , .

+13

-, : Haskell. , , ( getName), , , :

let f x = x
    g   = f
    h   = f
in  getName g == getName h
+4

- ? .

Prelude> let myNameIs::(a->b) -> String; myNameIs f = "myNameIs"
Prelude> :type myNameIs
myNameIs :: (a -> b) -> String
Prelude> myNameIs myNameIs
"myNameIs"
+1

, , , , ? :

data NamedFunction a b = NamedFunction { 
    name :: String,
    apply :: a -> b
}

timesTwo :: NamedFunction Int Int
timesTwo = NamedFunction "timesTwo" (\x -> 2 * x)

:

ghci> timesTwo `apply` 7
14
ghci> name timesTwo
"timesTwo"

Then you can write your own version (.):

-- contrast (.)  ::    (b -> c) ->          (a -> b) ->         (a -> c)
compose :: NamedFunction b c -> NamedFunction a b -> NamedFunction a c
compose (NamedFunction n1 f1) (NamedFunction n2 f2) = 
     NamedFunction (n1++ " . " ++ n2) (f1 . f2)

In ghci:

ghci> let f = timesTwo `compose` timesTwo in (f `apply` 7, name f) 
(28,"timesTwo . timesTwo")

You will have to redefine your own versions map, filteretc., and later you will encounter other problems, but maybe that's all you need ...

+1
source

All Articles