10

Haskellで独自の関数名を返す関数を実装することは可能ですか?

可能なタイプは(a -> b) -> String.

4

5 に答える 5

17

関数の引数を取り、その関数の名前に対応する定義サイト変数名を返す関数が必要ですか?

これはおそらくメタプログラミングなしではありません。これは通常、何か間違ったことをしている兆候です:)。しかし、そうでないと仮定すると、正しい方向に何かを達成する 1 つの方法は、Template Haskellを使用することです。これは、一意の名前 (コンパイラが物事に名前を付ける方法) を取得できます。例えば

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 を介して) Name を関数に渡すことでゲームをプレイできます。

ただし、あなたは確かにリフレクションとメタプログラミングの世界にいるので、あなたがやろうとしていることについてもっと知るのに役立ちます.

于 2013-03-07T14:40:18.423 に答える
6

ドンの投稿で言及されていることを明確にするために、Haskell では関数に名前がありません。関数をバインドする可能性のあるバインディングがありますが、getNameあなたが求めるような関数 (それを呼び出す) があった場合、これは何を返すと予想されますか:

let f x = x
    g   = f
    h   = f
in  getName g == getName h
于 2013-03-07T16:46:28.240 に答える
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"

その後、独自のバージョンの を作成できます(.)

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

ghci で:

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

map独自のバージョンのなどを再実装するfilter必要があり、後で他の問題に遭遇することになりますが、おそらくこれで十分です...

于 2013-03-07T17:11:40.507 に答える
0

何か不足していますか?この関数は、独自の関数名を返します。

Prelude> let myNameIs::(a->b) -> String; myNameIs f = "myNameIs"
Prelude> :type myNameIs
myNameIs :: (a -> b) -> String
Prelude> myNameIs myNameIs
"myNameIs"
于 2013-03-07T14:42:38.197 に答える