2016-10-14 4 views
4

私はハスケルにとって新しく、愚かな質問かもしれません。 私が望むのは、任意の演算子を引数として関数に渡すことです。たとえば :ハスケルの引数としての演算子

myFunc :: a -> Int -> Int -> Boolean 
myFunc operator a b = a operator b 

*Project> myFunc (>) 5 2 
True 
*Project> myFunc (<=) 5 2 
False 

はしてくださいことを行う方法の助言で私を助けて!

答えて

8

これは、haskell関数の引数で行うことができます。 上記の関数では、myFuncには、Intの2つの値をとり、Boolではなく、Booleanでない関数を使用する必要があります。その関数の宣言は(Int -> Int -> Bool)になります。したがって、次のように書くことができる:

myFunc :: (Int -> Int -> Bool) -> Int -> Int -> Bool 
myFunc op a b = a `op` b 

これはBool(二Int単数または複数)を返し2つのIntパラメータで関数を取り高次関数を定義します。他の関数パラメータと同様に使用できます。

myFunc (#) a b = a # b 

をまたは::これは正確にやってと同じであることを

myFunc (%) a b = a % b 

*または/、またはだけの特殊文字で構成される任意のオペレータが好きな中置operatersを使用しているため、あなたが何かを分割したいと思うたびに、`/`と入力すれば迷惑になるでしょう!)。

+1

「myFunc = id」はまったく同じことを言及する価値があります。 – leftaroundabout

+3

@leftaroundabout真実ですが、私はopの質問は明らかに単純な例で、大きな問題に適用すると思います。 – Majora320

+1

ありがとう!確かに、それは私の間違いでした。ブールの代わりにブール値を書きました –

6

フードの下では、機能は名前なしで「存在」します。 myFuncちょうどのように、あなたが定義した(または既にライブラリで定義されている)関数は、いずれも関数値で、です。この名前は、それを使用したい他のコードで参照する方法を提供します。これは、x = 3とまったく同じです。値3が名前xとは無関係に「存在」していれば、それを参照することができます。

これは、演算子を渡すことに関するあなたの質問に関連しているのはなぜですか?

まあ、限りHaskellのを懸念しているとして、><=のような演算子はも名前><=にバインドすることが起こるだけで無名関数です。演算子としての特殊な扱い(あなたが呼び出している引数の間に挿入することができます)は、という名前のところでであり、別の名前で参照すると変更されます。

ハスケルには2種類の名前があります。英数字の名前(英字、数字、アンダースコアのみ)、記号名(記号文字のみ)。あなたが表現{1} {2} {3}を持っている場合{2}がシンボリック名です(と{1}{3}シンボル名ではありません。そうしないと、構文エラーを持っている)場合は、その後、その表現は、「引数に{2}を呼び出す意味すると解釈され{1}{3} "。しかし、それらのどれもが象徴的な名前でなければ、それは代わりに "{2}{3}の引数に" を呼び出すと解釈されます。

しかし、このすべては、実際にそれらの名前で呼ば名前に、ではない機能を参照してのみ発生します。あなたはそのようなあなたのmyFuncを書くのであれば:

myFunc operator a b = operator a b 

そして、実際にmyFuncmyFunc (+) 1 2ようまたはmyFunc plus 1 2のように呼ばれていたかどうかは関係ありません。 myFuncの定義の中では、 "オペレータ"は英数字の名前であるoperatorという名前で参照されます。だから、あなたがそれを呼び出すときにまずそれを置いて、次に引数をつけてください。

代わりにあなたがそうのように、myFunc内のシンボリック名を使用することができmyFuncmyFunc plus 1 2などの非オペレータの機能で呼び出されたときに

myFunc ($&^*) a b = a $&^* b 

繰り返しますが、これはまたしても動作します。

もちろん、いずれかの種類の名前を他と同じように変換する方法があります。あなたはそれがオペレータのような中置使用するバッククォートで英数字の名前を入れることができます。

myFunc operator a b = a `operator` b 

そして、あなたは、単にカッコ内にシンボリック名を入れて、それが(にバインドされています関数への参照として使用することができ、これは事実でありますそのための引数を設けることなく、演算子を使用する唯一の方法):括弧内に演算子を置く:

myFunc ($^&*) a b = ($&^*) a b 

だから基本的に、あなたはあなたの関数にオペレータを渡すために知っておく必要なだけの特別な事はあなたがすでに知っていたものですあなたが関数を呼び出すとき。関数の定義の中で、他の関数とまったく同じように書くことができます。関数定義を選択した名前のスタイルは、それを演算子のように呼び出すか、通常の関数のように呼び出すかを決定します。関数の外にある演算子であるかどうかを知る必要はありません(実際にはが見つかりません)。もちろん


あなたが3つの以上のものと、複数の演算子を含むより複雑な式を持っている場合、その後、優先順位と結合の規則は起こっている正確に何を決定するために遊びに来ます。

関連する問題