質問

  1. 誰かが関数の構成の例を挙げますか?
  2. これは関数構成演算子の定義ですか?

    (.) :: (b -> c) -> (a -> b) -> a -> c
    f . g = \x -> f (g x)
    

これは、2つの関数を取り、関数を返すことを示していますが、誰かが英語で論理を表現したことを覚えています

少年は人間です - >アリは男の子です - >アリは人間です

  1. このロジックは関数構成に関連していますか?
  2. 関数アプリケーションと組成の強力な結合の意味は何ですか?また、どちらが他方よりも強力な結合ですか?

助けてください。

ありがとう。

役に立ちましたか?

解決

(編集1: 私はあなたの質問のいくつかのコンポーネントを初めて見逃しました。私の答えの一番下を見てください。)

この種の声明について考える方法は、タイプを見ることです。あなたが持っている議論の形式は三段論法と呼ばれます。しかし、私はあなたが何かを忘れていると思います。さまざまな種類の三段論法があり、あなたのものは、私が知る限り、関数の構成に対応していません。一種の三段論法を考えてみましょう。

  1. それが晴れているなら、私は熱くなります。
  2. 暑くなったら泳ぎに行きます。
  3. したがって、 それが晴れているなら、私は泳ぎに行きます。

これはaと呼ばれます 仮説的な三段論法. 。論理用語では、次のように書きます。 s 「それは晴れている」という命題を表してください。 h 「私は熱くなります」という命題を表し、 w 「私は水泳に行きます」という命題を表します。書き込み αβ にとって "α 示す β"、そして「したがって」のために書いて、上記を次のように翻訳できます。

  1. sh
  2. hw
  3. sw

もちろん、これは交換すると機能します s, h, 、 と w 任意の任意の場合 α, β, 、 と γ. 。今、これはおなじみに見えるはずです。意味の矢印→を変化させると、関数矢印に ->, 、これはなります

  1. a -> b
  2. b -> c
  3. a -> c

そして、見よ、組成演算子のタイプの3つのコンポーネントがあります!これを論理的な三段論法と考えるには、以下を考慮することができます。

  1. タイプの値がある場合 a, 、タイプの値を作成できます b.
  2. タイプの値がある場合 b, 、タイプの値を作成できます c.
  3. したがって、 タイプの値がある場合 a, 、タイプの値を作成できます c.

これは理にかなっているはずです:in f . g, 、関数の存在 g :: a -> b 前提1は真実であることを伝えます f :: b -> c 前提2が真実であることを伝えます。したがって、あなたは関数のために最終的なステートメントを締めくくることができます f . g :: a -> c 証人です。

あなたの三段論法が何に翻訳されるかは完全にはわかりません。それはほとんどの例です モーダスポーネン, 、しかし、そうではありません。 Modus ponensの引数は、次の形式を取ります。

  1. 雨が降っている場合は、濡れます。
  2. 雨が降っている。
  3. したがって、 私は濡れます。

書き込み r 「雨が降っている」と w 「私は濡れます」のために、これは私たちに論理的な形を与えます

  1. rw
  2. r
  3. w

意味矢印を関数矢印に置き換えると、次のことがわかります。

  1. a -> b
  2. a
  3. b

そして、これは単に関数アプリケーションです。 ($) :: (a -> b) -> a -> b. 。これを論理的な議論と考えたい場合、それは形のかもしれません

  1. タイプの値がある場合 a, 、タイプの値を作成できます b.
  2. タイプの値があります a.
  3. したがって、 タイプの値を作成できます b.

ここでは、表現を考えてください f x. 。関数 f :: a -> b 命題1の真実の証人です。値 x :: a 命題2の真実の証人です。したがって、結果はタイプになります b, 、結論を証明します。それはまさに私たちが証明から見つけたものです。

さて、あなたの元の三段論法は次の形式を取ります:

  1. すべての男の子は人間です。
  2. アリは男の子です。
  3. したがって、 アリは人間です。

これをシンボルに翻訳しましょう。 BX それを示します バツ 男の子です。 HX それを示します バツ 人間です。 a アリを表します。と∀バツ. φ それは言う φ のすべての値に当てはまります バツ. 。それから私たちは持っています

  1. バツ. BXHX
  2. ba

これはほぼモデアですが、すべてをインスタンス化する必要があります。論理的に有効ですが、タイプシステムレベルでそれを解釈する方法がわかりません。誰かが助けたいなら、私はすべて耳です。推測の1つは、ランク2タイプのようなものです (forall x. B x -> H x) -> B a -> H a, 、しかし、私はそれが間違っていると確信しています。別の推測は、ようなよりシンプルなタイプです (B x -> H x) -> B Int -> H Int, 、 どこ Int アリの略ですが、繰り返しますが、私はそれが間違っていると確信しています。繰り返しますが、あなたが知っているなら、私にも知らせてください!

そして最後のメモ。このように物事を見る - 証明とプログラムの間のつながりに耐える - は、最終的にの深い魔法につながります カレー - ハワード同型, 、しかし、それはより高度なトピックです。 (本当にかっこいい!)


編集1: また、関数構成の例を求めました。これが一例です。私が人々のミドルネームのリストを持っているとします。すべてのミドルイニシャルのリストを作成する必要がありますが、そのためには、まずすべての存在しないミドルネームを除外する必要があります。ミドルネームがnullであるすべての人を除外するのは簡単です。私たちはただ 含む ミドルネームがあるすべての人 いいえ null filter (\mn -> not $ null mn) middleNames. 。同様に、私たちは誰かの真ん中のイニシャルで簡単に取得できます head, 、そして、単に必要です map head filteredMiddleNames リストを取得するため。つまり、次のコードがあります。

allMiddleInitials :: [Char]
allMiddleInitials = map head $ filter (\mn -> not $ null mn) middleNames

しかし、これは刺激的に具体的です。私たちは本当に中心的な生成関数が欲しいです。それでは、これを1つに変更しましょう。

getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames = map head $ filter (\mn -> not $ null mn) middleNames

さて、何か面白いことを見てみましょう。関数 map タイプがあります (a -> b) -> [a] -> [b], 、 それ以来 head タイプがあります [a] -> a, map head タイプがあります [[a]] -> [a]. 。同様に、 filter タイプがあります (a -> Bool) -> [a] -> [a], 、 など filter (\mn -> not $ null mn) タイプがあります [a] -> [a]. 。したがって、パラメーターを取り除くことができ、代わりに書くことができます

-- The type is also more general
getFirstElements :: [[a]] -> [a]
getFirstElements = map head . filter (not . null)

そして、あなたは私たちには構成のボーナスインスタンスがあることがわかります: not タイプがあります Bool -> Bool, 、 と null タイプがあります [a] -> Bool, 、 それで not . null タイプがあります [a] -> Bool: :最初に指定されたリストが空であるかどうかをチェックし、次にそれを返すかどうかを返します そうではありません. 。ちなみに、この変換は関数を変えました ポイントフリースタイル;つまり、結果の関数には明示的な変数がありません。

また、「強力なバインディング」についても尋ねました。私があなたが言及していると思うのは、 .$ オペレーター(およびおそらく機能アプリケーション)。 Haskellでは、算術と同様に、特定の演算子は他の演算子よりも優先され、したがってよりしっかりと結合します。たとえば、式で 1 + 2 * 3, 、これは解析されます 1 + (2 * 3). 。これは、Haskellでは、次の宣言が有効であるためです。

infixl 6 +
infixl 7 *

数(優先度レベル)が高いほど、その演算子が呼び出されるのは早く、したがってオペレーターがバインドします。関数アプリケーションは効果的に無限の優先順位を持っているため、最も緊密に結合します:式 f x % g y ASとして解析します (f x) % (g y) 任意のオペレーターの場合 %. 。 . (構成)と $ (アプリケーション)オペレーターには、次の固定宣言があります。

infixr 9 .
infixr 0 $

優先レベルはゼロから9の範囲であるため、これが言っているのは . オペレーターがバインドします もっと 他のどの(関数アプリケーションを除く)よりも厳密に $ バインド 以下 しっかりと。したがって、式 f . g $ h ASとして解析します (f . g) $ h;そして実際、ほとんどのオペレーターにとって、 f . g % h そうなるでしょう (f . g) % hf % g $ h そうなるでしょう f % (g $ h). 。 (唯一の例外は、他のゼロまたは9つの優先順位演算子がまれであることです。)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top