私が使用して試した、どこでもmap
、fmap
うまくとして働いています。Haskellの作成者はなぜmap
関数の必要性を感じたのですか?それだけで、現在として知られているものであることができなかったfmap
し、fmap
言語から削除されるだろうか?
fmap
ます。Functorインスタンスに関数をマッピングすることです。に特化した目的はなんとおもいますかmap
。
私が使用して試した、どこでもmap
、fmap
うまくとして働いています。Haskellの作成者はなぜmap
関数の必要性を感じたのですか?それだけで、現在として知られているものであることができなかったfmap
し、fmap
言語から削除されるだろうか?
fmap
ます。Functorインスタンスに関数をマッピングすることです。に特化した目的はなんとおもいますかmap
。
回答:
オーガストのコメントに注目するために答えたい:
それは実際にそれが起こる方法ではありません。起こったことは、マップのタイプがHaskell 1.3のFunctorをカバーするように一般化されたことです。つまり、Haskell 1.3ではfmapはmapと呼ばれていました。この変更はHaskell 1.4で元に戻され、fmapが導入されました。この変更の理由は教育的でした。初心者にHaskellを教えるとき、非常に一般的なタイプのマップはエラーメッセージを理解することをより難しくしました。私の意見では、これは問題を解決する正しい方法ではありませんでした。
Haskell 98は一部のHaskellers(私を含む)によって一歩後退したと見なされており、以前のバージョンではより抽象的で一貫性のあるライブラリが定義されていました。しかたがない。
map and fmap
長い時間を回避されている-それは、2006年8月にはHaskellプライムメーリングリストで再加熱した- haskell.org/pipermail/haskell-prime/2006-August/thread.html。カウンターポイントとして、私は現状維持を好む。私にとって、ミランダにほぼ対応するHaskellのサブセットがあることは価値があるようです。英国では、ミランダはコンピュータサイエンスの学生だけでなく、数学の学生の教育言語としても使用されていました。そのニッチが非関数型言語(Mathematicaなど)でまだ失われていない場合、Haskellが統一された形でmap
満たすことはありません。
https://wiki.haskell.org/Typeclassopedia#FunctorのFunctor
ドキュメントからの引用
別の
map
関数が必要な理由を尋ねるかもしれません。現在のリストのみのmap
関数を廃止し、 代わりに名前fmap
を変更しmap
ないのはなぜですか?まあ、それは良い質問です。通常の議論は、Haskellを学んだばかりの人は、map
間違って使用すると、リストについてのエラーではなく、についてのエラーが表示されるということFunctor
です。
アプリケーションサイトでは同じように見えますが、もちろん異なります。これら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
と、まったく異なるものが表示されます。
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)