🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

関数型プログラミング

関数型プログラミングとは、関数を用いて演算子を構築し、算出し、コンピュータプログラムを構成する枠組みです。

Q&A

解決済

3回答

3297閲覧

Haskell: 3変数関数を中置演算子にしたい、あるいは真ん中の引数だけ指定したい

退会済みユーザー

退会済みユーザー

総合スコア0

Haskell

Haskellは高い機能性をもった関数型プログラミング言語で、他の手続き型プログラミング言語では難しいとされている関数でも容易に行うことができます。強い静的型付け、遅延評価などに対応しています。

関数型プログラミング

関数型プログラミングとは、関数を用いて演算子を構築し、算出し、コンピュータプログラムを構成する枠組みです。

0グッド

2クリップ

投稿2019/11/01 05:39

Haskellの関数についての質問2つです。

適当な3変数関数(例えば下のような)があったとします。

Haskell

1func :: Int -> Int -> Int -> Int 2func a b c = a + 2*b + 3*c 3 4> func 1 2 3 514

①引数を一つだけ指定して2変数関数として、さらに``で囲って中置演算子にしようとしてもできませんでした。

Haskell

1> 2 `func 1` 3 2<interactive>:93:9: error: parse error on input1

これは何故できないのでしょうか。

②3つの引数の内2番目または3番目についてのみ具体的に指定することで2変数関数として扱うことは可能でしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

igrep

2019/11/01 05:54

「2変数関数」ではなく「2引数関数」という言い方の方が慣習的によく使いますね。
退会済みユーザー

退会済みユーザー

2019/11/01 08:18

ありがとうございます。
guest

回答3

0

ベストアンサー

これは何故できないのでしょうか。

kakkun61さんの回答のとおり、残念ながら「そういう仕様だ」としか答えようがないですね...????
個人的にも GHC Proposals で提案しようかと思ったことがあるぐらい欲しい機能ではあります。

ただ、その場合一つ懸念すべき点があります。
演算子を定義した場合、次のように infixlinfixrinfixというキーワードで、演算子の結合の優先順位や結合の方向を指定できるようになっています。

infixr 0 $ infixl 1 >>

実はこれは名前が記号だけの関数(記号関数)だけでなく、普通の名前の関数にも指定できます。
例えば、elem関数やdiv関数をGHCiの:iで調べてみると、infixlinfixが指定されてることがわかります。

ghci> :i div ... infixl 7 `div` ghci> :i elem infix 4 `elem`

なぜこんな指定ができるようになっているかというと、そう、divelemを問題のバッククォートで囲って中置関数として使った場合の優先順位のためなんです。

つまり、バッククォートの中で自由な式を書いた場合、結合をどのような優先順位で解決するかがわからなくなってしまう、という問題があるのです(デフォルトをそのまま採用するというのは、場合によっては問題になり得ますが一案です)。
この問題をちゃんと解決できれば、採用される可能性はあるんじゃないかと企んでいます。

3つの引数の内2番目または3番目についてのみ具体的に指定することで2変数関数として扱うことは可能でしょうか。

一旦別の関数を定義するか、あるいは想像されている使い方と異なるかも知れませんが、Haskellの性質上、引数が3つ以上でも、実はそのままバッククォートで囲って中置記法が使えます。

質問者にあげていただいた func を例に説明するとこう????

ghci> (1 `func` 2) 3 14

要するに、バッククォートを使って中置関数として使って両辺に値を適用した状態でも、返す値が関数になっていれば、そのままもう一つの引数を適用できるのです。

投稿2019/11/01 06:17

編集2019/11/01 06:21
igrep

総合スコア433

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/11/01 08:31

回答ありがとうございます。 ①現状はできない旨把握しました。 ②引数3つでも中置できるんですね(言われてみれば確かにそうですね)。ありがとうございます。
guest

0

ひとつめの質問について

Haskell 2010 Language Report ではバックチックを使った項について次のように定義されています。

ですので、バックチックの間には変数・モジュール名付き変数・構築子・モジュール名付き構築子しか書けません。

varop → varsym | ` varid ` (variable operator) qvarop → qvarsym | ` qvarid ` (qualified variable operator) conop → consym | ` conid ` (constructor operator) qconop → gconsym | ` qconid ` (qualified constructor operator)

ふたつめの質問について

名前を付ける必要があると思います。
(もしかすると何かパッケージにそういう機能を提供しているものがあるかもしれませんが。)

haskell

1foo :: Int -> Int -> Int -> Int 2 3-- 1番目 4foo1 = foo 1 5 6-- 2番目 7foo2 a c = foo a 2 c 8 9-- 3番目 10foo3 a b = foo a b 3

投稿2019/11/01 06:07

編集2019/11/01 06:17
kakkun61

総合スコア285

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/11/01 08:25

回答ありがとうございます。 ・ひとつめ 仕様上できないのですね。 ・ふたつめ 名前を付けるのが必要、把握しました。
guest

0

②の質問について,composition-extraというライブラリの提供している-$--$を使うと書くことができます(ただ実際のコードでこれが使われているかどうかは分かりません.少なくとも私は見たことがないです).

haskell

1>>> (func -$ 2) 1 3 -- 2番目を先に指定 214 3>>> (func --$ 3) 1 2 -- 3番目を先に指定(シンタックスハイライトが崩れてますが実際はちゃんと動きます) 414

余談ですがこの記号の由来は-$--$-をscalaのプレースホルダのように読むことが想定されているようです.例えば2つ目の例はfunc _ _ 3と読めます.

投稿2019/11/01 08:54

編集2019/11/01 08:59
nhogeyama

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問