map、fmap、liftMがあるのはなぜですか?


102
map :: (a -> b) -> [a] -> [b]

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

liftM :: Monad m => (a -> b) -> m a -> m b

本質的に同じことをする3つの異なる関数があるのはなぜですか?


32
主に歴史。fmapは教育上の理由からmapとは異なり、liftMは歴史的な理由からfmapとは異なります(Functorはモナドのスーパークラスではありません)
luqui

12
ああ、そして明確にするために:彼らは「本質的に」同じことをしません。両方ともmap、とまったく同じことをliftM間違いなく行うはずです。fmap
CAマッキャン

2
一方でfmapliftMまったく同じことを行う、mapもちろん彼らの唯一の特殊なケース、つまり何か異なっています。fmap id getLineよく型付けされてmap id getLineいますが、そうではありません。
Thorsten 2017

回答:


91

mapリストの操作を簡略化するために存在し、歴史的な理由から(fmapがある場合のHaskellのmapのポイントは何ですか?を参照)。

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

- Typeclassopedia、ページ20

fmapそしてliftM、モナドはHaskellでは自動的にファンクタではなかったので存在します:

fmapとliftMの両方があるという事実は、数学的にはすべてのモナドがファンクターであるにもかかわらず、Monad型クラスがFunctorインスタンスを必要としないという事実の不幸な結果です。ただし、fmapとliftMは基本的に交換可能です。これは、Functorのインスタンスではなく、どのタイプもMonadのインスタンスになるのは(技術的な意味ではなく社会的な意味での)バグであるためです。

- Typeclassopedia頁33

編集:のagustussの歴史mapfmap

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

- FMAPがあるハスケル、内マップのポイントは何ですか?


13
そして、@ augustssが説明する変更から10年以上経って最初にHaskellに出会った人が作られ、現在言語を学んでいる人を助けるために多くの時間を費やしてきたという私の観点から、それが助けになったことはまったく明らかではありませんとにかく。無駄な冗長性を相殺するには十分ではありません(それ自体が、このような質問をする人々につながります)。このFunctorクラスは一般的すぎて無視できず、初心者はとにかくエラーメッセージに混乱することがよくあります。
CAマッキャン2011

10
削除できませんliftMか?気になる人はコードを壊してみましょう。通常、コードがgithubで修正されてハッキングでアップロードされるまで2日未満です。それとも私はワイルドでクレイジーですか?
Tarrasch 2011

1
@Tarrasch:すべてのパッケージがgithubを使用しているわけではありません。すべてのパッケージが時間どおりに更新された優れた実績があるわけではありません。私が使用する場合に適しているためなどでliftMはなく、doブロックで使用する傾向がありfmapますliftM2。同じように。
ivanm 2011

1
@ L01manの人々はこれに取り組んできました。参照stackoverflow.com/questions/5730270/...をし、数値クラスのため、少なくとも、選択肢があります:hackage.haskell.org/packages/archive/numeric-prelude/0.3.0.2/...
li.davidm

1
@ L01manはい、これはすぐに修正されます。Applicativeのモナドの提案、それはハスケルの次のバージョンに渡しますように(AMP)が見えます。GHC 7.8.3に--fwarn-amp、移行のために既存のコードを更新するのに役立つ新しいフラグがあります。
recursion.ninja 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.