質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

91.27%

  • Haskell

    44questions

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

関数合成の際の恒等式(?)について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 95

Haskell の関数合成でよくわからなくなったので、質問させてください。

f = \x -> x+2
g = \x -> x*2

の時、

  • f $ g 2
  • f.g 2
  • (f.) g 2
  • (.g) f 2

すべて等しくなります。

import Data.Char
f = ord
g = chr


でも同様です。
一般に

f $ g x == (f.g) x == (f.) g x == (.g) f x 


が成立するのでしょうか?
最後の (.g) だけ違和感があるのですが。。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • igrep

    2017/12/19 12:37 編集

    `f.g 2` ではなく `(f.g) 2` ではありませんか? 後半の恒等式では `(f.g) 2` となっていますが、念のため。

    キャンセル

  • takagitakashi

    2017/12/19 13:13

    おはずかしい。その通りでございます。

    キャンセル

回答 3

checkベストアンサー

+1

(.g) f x について、

f.g = \x -> f (g x)なので

(.g) = \f -> \x -> f (g x)
((.)g(.g)の違いに注意)

つまり
(.g) f x = f (g x)

なのかなぁ?


中置演算子opに対する部分適用:
(f op)(op g)が何になるかは以下参考

Haskell のセクションと中置記法

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/19 13:23

    (.) g と (.g)の違いに注意、とありますが、どのように違うのでしょうか?

    *Main> let g = (+2)
    *Main> :t g
    g :: Num a => a -> a
    *Main> :t (.g)
    (.g) :: Num b => (b -> c) -> b -> c
    *Main> :t ((.) g)
    ((.) g) :: Num c => (a -> c) -> a -> c

    違いが無いように見えるのですが。。。

    キャンセル

  • 2017/12/19 13:31

    2つともb,cで表すように
    後者のaをbにして揃えると
    Num b => (b -> c) -> b -> cと
    Num c => (b -> c) -> b -> cですけど

    キャンセル

  • 2017/12/19 13:37 編集

    なるほど。型が違うんですね。
    ご教示いただいたサイトの表記だと、
    (`op` g) と (op g)
    の違い、ということですね。

    キャンセル

  • 2017/12/19 13:37

    型が違うので意味も違います。
    参考リンクにも例で出てくる/がわかりやすいかと
    (/)2は2を割る
    (/2)は2で割る
    のように

    キャンセル

  • 2017/12/19 13:38

    あ、、すいません、入れ違いになってしまいました。。よく理解できました!重ね重ねありがとうございます。

    キャンセル

+1

お二人に回答いただき、以下は常に成立する(というより定義?)という理解に達しました。

op f g
= f op g
= (f op) g
= (op g) f

なので、op = . のとき

(.) f g
= f.g
= (f.) g
= (.g) f

ありがとうございました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

(.g) hoge や f hoge といった関数呼び出しは左結合なので、

(.g) f x にカッコを補うと ((.g) f) x となります。

で、ご存じのとおり (.g) f は f.g と等価なので、
((.g) f) x は結果 ((f.g) x) と等価になります。

(f.) g x についても同様で、カッコを補うと ((f.) g) x になることから、
(f.) g は (f.g) と等価なので、
((f.) g) x は ((f.g) x) と等価になります。

f $ g x についても、ご認識の通りです。
一般によくある書き換えイディオムとして覚えておくといいと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/19 13:12

    回答ありがとうございます。
    かっこの補い、お手間かけます。。。
    自分が聞きたいのは、
    「(.g) fは (f.g) と等価」
    「(f.) gは (f.g)と等価」
    の理由なのですが、、、
    これは自明なんでしょうか?

    キャンセル

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

ただいまの回答率

91.27%

関連した質問

同じタグがついた質問を見る

  • Haskell

    44questions

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