Function to output function name

孤人 提交于 2019-12-18 04:53:14

问题


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

A possible type could be (a -> b) -> String.


回答1:


You want a function that takes a function argument, and returns the definition site variable name that corresponds to the name of that function?

This isn't possibly without meta-programming, which is usually a sign you're doing something wrong :). But assuming you're not, one way to achieve something in the right direction is via Template Haskell, which can get at unique names (how the compiler names things). E.g.

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)"

And now we know a lot about the variable. So you can play games by passing a Name to the function (via 'f) rather than f itself.

You are certainly in the world of reflection and meta-programming though, so it would help to know more about what you are trying to do.




回答2:


To clarify something mentioned in dons' post: no functions have names in Haskell. There are bindings which may bind functions, but if I had such a function (call it getName) as you seek then what would you expect this to return:

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



回答3:


I don't know what you need it for, but maybe a simplistic solution suffices? Like so:

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

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

which you can use as follows:

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

You can then write your own version of (.):

-- 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'll have to reimplement your own versions of map, filter and so on, and you're bound to run into other problems later, but maybe this is all you need...




回答4:


Am I missing something? This function returns its own function name.

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


来源:https://stackoverflow.com/questions/15272231/function-to-output-function-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!