1. ホーム
  2. functional-programming

[解決済み】関数型プログラミングで、ファンクターとは何ですか?

2022-04-03 03:19:45

質問

関数型プログラミングに関するさまざまな記事を読んでいると、「ファンクタ」という用語に何度か出会いますが、著者は通常、読者がこの用語をすでに理解していることを前提にしています。しかし、著者は読者がこの用語をすでに理解していると仮定しています。ウェブで調べても、過度に技術的な説明しかありません。 ウィキペディアの記事 または信じられないほど曖昧な説明です。 ocamlチュートリアルサイト ).

どなたか、この用語を定義し、その用途を説明し、ファンクタの作成方法と使用方法の例を示していただけませんか?

編集 : この言葉の背景にある理論には興味がありますが、私はその理論よりも、その概念の実装と実用に興味があります。

編集2 : 何か用語の掛け合わせがあるようですね。C++の関数オブジェクトではなく、関数型プログラミングのファンクタのことを指しているのです。

どのように解決するのか?

ファンクターという言葉は、数学の中でも非常に一般的で抽象的なカテゴリー理論に由来しています。 関数型言語の設計者は、少なくとも2つの異なる方法でこの言葉を借用しています。

  • ML言語群では,ファンクタは1つ以上の他のモジュールをパラメータとするモジュー ルである. これは高度な機能と考えられており,ほとんどの初級プログラマは,この 機能を使いこなすのに苦労しています.

    実装と実用の例として、好きな形のバランス2分木をファンクタとしてきっぱりと定義し、それを提供するモジュールをパラメータとして受け取ることができる。

    • バイナリツリーで使用されるキーの種類

    • キーの総順序付け関数

    これさえできれば、同じバランス2分木の実装をずっと使い続けることができる。 (ツリーに格納される値のタイプは通常ポリモーフィックなままです。ツリーはコピーする以外に値を見る必要はありませんが、キーを比較できる必要があるのは確かで、ファンクタのパラメータから比較関数を取得します)。

    MLファンクタのもう一つの応用例として 層状ネットワークプロトコル . このリンクはCMUのFoxグループによる非常に素晴らしい論文で、ファンクタを使用して、より単純な層(IPや直接イーサネット上など)の上に(TCPのように)より複雑なプロトコル層を構築する方法を示しています。 各レイヤーは、その下のレイヤーをパラメータとするファンクタとして実装されています。 ソフトウェアの構造は、プログラマーの頭の中にだけ存在する層とは対照的に、人々が問題について考える方法を実際に反映している。 この作品が発表された1994年当時は、大きな話題となった。

    MLファンクタが実際に使われているワイルドな例としては、次のような論文を見ることができます。 MLモジュールマニア この例では、ファンクタの動作について、出版可能な(つまり、怖い)例が含まれています。 MLのモジュールシステムについての(他の種類のモジュールとの比較も含めた)素晴らしく、明確で分かりやすい説明は、Xavier Leroyの1994年の素晴らしいPOPL論文の最初の数ページを読んでください。 マニフェスト型、モジュール、そして独立したコンパイル .

  • Haskellや、関連する純粋関数型言語において。 Functor 型クラス . 型がある期待される振る舞いで特定の操作を提供するとき、型は型クラスに属します(より技術的には、型は"is an instance of" the type class)。 型は T は、クラス Functor が、ある種のコレクション的な振る舞いをする場合。

    • タイプ T は別の型にパラメータ化されており、これはコレクションの要素型と考えるべきでしょう。 コレクション全体の型は次のようになる。 T Int , T String , T Bool それぞれ、整数、文字列、ブール値を含む場合。 要素の型が不明な場合は 型パラメータ a というように T a .

      例としては、リスト(0個以上の要素で、型は a ) のような Maybe 型(0個または1個の型の要素 a ) 、型の要素のセット a 型の要素の配列 a 型の値を含むあらゆる種類のサーチツリー。 a などなど、思いつくものはたくさんあります。

    • もう1つのプロパティは T を満たす必要があります。 a -> b (要素に対する関数)、そしてその関数を受け取り、関連するコレクションに対する関数を生成できる必要があります。 これを行うには、演算子 fmap のすべての型に共通するものです。 Functor 型クラスです。 この演算子は実際にはオーバーロードされているので、もし関数 even という型を持つ Int -> Bool であれば

      fmap even
      
      

      は、多くの素晴らしいことを行うことができるオーバーロードされた関数です。

      • 整数のリストをブール値のリストに変換する

      • 整数の木をブール値の木に変換する

      • 変換する Nothing から NothingJust 7 から Just False

      Haskellでは,この性質は fmap :

      fmap :: (Functor t) => (a -> b) -> t a -> t b
      
      

      ここで、小さな t での任意の型を意味します。 Functor クラス."。

    長い話を短くすると、Haskellでは ファンクターとは、要素に対する関数が与えられた場合のコレクションの一種です。 fmap は、コレクションに関する関数を返します。 . 想像できるように、これは広く再利用できるアイデアなので、Haskellの標準ライブラリの一部として祝福されているわけです。

いつものように、人々は新しい便利な抽象化機能を発明し続けています。 アプリケーティブ という論文が最も良い参考となるでしょう。 エフェクトを用いた応用プログラミング Conor McBrideとRoss Patersonによるものです。