fmapがある場合、Haskellのmapのポイントは何ですか?


97

私が使用して試した、どこでもmapfmapうまくとして働いています。Haskellの作成者はなぜmap関数の必要性を感じたのですか?それだけで、現在として知られているものであることができなかったfmapし、fmap言語から削除されるだろうか?


11
「Haskellのfmapのポイントは何ですか?」
zw324 '26 / 07/26

11
私はそのポイントが何であるかを知っていfmapます。Functorインスタンスに関数をマッピングすることです。に特化した目的はなんとおもいますかmap
クラークゲーベル、2011

回答:


95

オーガストのコメントに注目するために答えたい:

それは実際にそれが起こる方法ではありません。起こったことは、マップのタイプがHaskell 1.3のFunctorをカバーするように一般化されたことです。つまり、Haskell 1.3ではfmapはmapと呼ばれていました。この変更はHaskell 1.4で元に戻され、fmapが導入されました。この変更の理由は教育的でした。初心者にHaskellを教えるとき、非常に一般的なタイプのマップはエラーメッセージを理解することをより難しくしました。私の意見では、これは問題を解決する正しい方法ではありませんでした。

Haskell 98は一部のHaskellers(私を含む)によって一歩後退したと見なされており、以前のバージョンではより抽象的で一貫性のあるライブラリが定義されていました。しかたがない。


16
これらの後方ステップはどこかで収集され、文書化されていますか?他に何がバックステップと見なされたか、そしてそれらに対してより良い解決策があるかどうかを確認することは興味深いでしょう。
Davorak 2011

3
map and fmap長い時間を回避されている-それは、2006年8月にはHaskellプライムメーリングリストで再加熱した- haskell.org/pipermail/haskell-prime/2006-August/thread.html。カウンターポイントとして、私は現状維持を好む。私にとって、ミランダにほぼ対応するHaskellのサブセットがあることは価値があるようです。英国では、ミランダはコンピュータサイエンスの学生だけでなく、数学の学生の教育言語としても使用されていました。そのニッチが非関数型言語(Mathematicaなど)でまだ失われていない場合、Haskellが統一された形でmap満たすことはありません。
スティーブンテトリー

35
そして、まだ気づいていない人のために、8月はLennart Augustssonであり、Haskellが存在する以前からすべての目的のためにHaskellコミュニティの一部であったことを指摘しておきます。Haskellの歴史ですから、問題のコメントは決して間接的な噂ではありません!
CAマッキャン

3
Haskell wikiにNitpicksのページがあり、この問題が言及されています。
Alexey

私がHaskellを学ぶときはいつもfmapとflatmapを混同していたので、この決定が教育上の理由で行われたのはおかしいです。彼らはn00bフォーカスグループを一緒に取得する必要があります。:)
Danny Andrews

27

https://wiki.haskell.org/Typeclassopedia#FunctorFunctorドキュメントからの引用

別のmap関数が必要な理由を尋ねるかもしれません。現在のリストのみのmap関数を廃止し、 代わりに名前fmapを変更しmapないのはなぜですか?まあ、それは良い質問です。通常の議論は、Haskellを学んだばかりの人は、map間違って使用すると、リストについてのエラーではなく、についてのエラーが表示されるということFunctorです。


1
これは私には非常に理にかなっています。
hbobenicio 2017

25

アプリケーションサイトでは同じように見えますが、もちろん異なります。これら2つの関数、mapまたはのいずれかをfmap値のリストに適用すると、同じ結果が得られますが、同じ目的のためのものではありません。

GHCIセッション(Glasgow Haskell Compiler Interactive)を実行して、これら2つの関数に関する情報を照会し、それらの実装を確認すると、多くの違いが見つかります。

地図

GHCIに問い合わせて map

Prelude> :info map
map :: (a -> b) -> [a] -> [b]   -- Defined in ‘GHC.Base’

これは、任意の型aの値のリストを生成する任意の型の値のリストに適用可能な高次関数として定義されていることがわかりますb。(多型がa及びb任意のタイプのための上記定義のスタンドに)map機能に適用されることが意図されている値のリストのHaskellに他の多くの中ただ一つの可能なデータ型です。mapこの関数は、値のリストではない何かに適用することができませんでした。

GHC.Baseソースコードから読み取れるmapように、関数は次のように実装されています

map _ []     = []
map f (x:xs) = f x : map f xs

これは、パターンマッチングを使用してリストの先頭(the x)を末尾(the xs)から引き離し、:(cons)値コンストラクターを使用して新しいリストを作成して、先頭に追加しますf x「fをxに適用」と読みます)。mapリストが空になるまで、尾の上の再帰へ。map関数の実装が他の関数に依存するのではなく、それ自体に依存することは注目に値します。

fmap

次に、情報についてクエリを実行するfmapと、まったく異なるものが表示されます。

Prelude> :info fmap
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
  ...
  -- Defined in ‘GHC.Base’

今回fmapは、Functor型クラスに属したいデータ型によって実装を提供する必要がある関数の1つとして定義されます。つまり、「値のリスト」データ型だけでなく、fmap関数の実装を提供できる複数のデータ型が存在する可能性があります。これはfmap、はるかに大きなデータ型のセットに適用できます。

GHC.Baseソースコードから読み取れるように、fmap関数の可能な実装は、Maybeデータ型によって提供されるものです。

instance  Functor Maybe  where
  fmap _ Nothing       = Nothing
  fmap f (Just a)      = Just (f a)

もう1つの可能な実装は、2タプルデータ型によって提供されるものです。

instance Functor ((,) a) where
  fmap f (x,y) = (x, f y)

もう1つの可能な実装は、リストデータ型によって提供されるものです(もちろん!)。

instance  Functor []  where
  fmap f xs = map f xs

これはmap関数に依存しています。

結論

map一方、関数は(値は任意のタイプである)値のリスト以外の何ものにも適用できるfmap機能は多くのデータ型を適用することができます:ファンクタクラスに属しているもの(例えばmaybes、タプル、リストなどのすべて)。以来、「値のリスト」、次いで(それのための実装を提供するため)データ型はファンクタでもありfmap、ならびに非常に同じ結果を生成しているにも適用することができますmap

map  (+3) [1..5]
fmap (+3) (Just 15)
fmap (+3) (5, 7)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.