2017-09-02 6 views
1

traverseを実行するために、Applicativeインターフェイスから正確に何が必要なのかを理解しようとしています。制約が厳格であるかのようにデフォルトの実装では使用されないので、私は立ち往生しています。 Haskellのタイプシステムは実際の要件を記述するには弱すぎるのでしょうか?Applicative、FoldableとTraversableの関係は何ですか?

-- | Map each element of a structure to an action, evaluate these actions 
-- from left to right, and collect the results. For a version that ignores 
-- the results see 'Data.Foldable.traverse_'. 
traverse :: Applicative f => (a -> f b) -> t a -> f (t b) 
traverse f = sequenceA . fmap f 

-- | Evaluate each action in the structure from left to right, and 
-- and collect the results. For a version that ignores the results 
-- see 'Data.Foldable.sequenceA_'. 
sequenceA :: Applicative f => t (f a) -> f (t a) 
sequenceA = traverse id 

おそらく関連する側の質問、なぜsequenceA_Foldableで定義されていますか?

+1

[Traversable typeclassの目的](https://stackoverflow.com/questions/45798242/the-purpose-of-the-traversable-typeclass)の可能な複製 – user2407038

+0

2番目の質問は1番目とは全く関係がないようです。しかし答えは簡単です: 'Foldable'は' sequenceA_'を実装するのに十分強力です。 – user2407038

答えて

3

traverseおよびsequenceAは、Traversableが空の場合に何が起こるかを処理する必要があります。次に、他のものにグロムするために使用できるApplicativeコンテキストの要素がないので、pureが必要になります。

あなたが指摘したように、相互に依存しているので、あなたが提示した定義は少し誤解を招きます。実際にそれらのいずれかを実装するには、空のコレクションの問題にぶつかります。そして、の必要性にぶつかるでしょう。Functorは、いくつかのファンクタfに対して異なる値f aを集約する機能を提供していません。ほとんどの種類のために、traverseまたはsequenceAのいずれかを実施するために、あなたはApplicativeが提供するツールが必要になりますので、

したがってApplicative制約があります。

これは、あなたがpureを必要としないか、<*>を必要としない特定のタイプがあると言われています。あなたのコレクションが空にならない場合は、pureは必要ありません。 NonEmpty。コレクションに複数の要素が含まれていない場合は、<*>を必要としません。 Maybe。時にはあなたはどちらかを必要とせず、ちょうどfmapで逃げることができます。タプルセクション、例えば(a,))。

Haskellは、あなたが弱いと Traversable(例えば TraversableNonEmptyTraversableSingleton)の異なるバージョンを作成できるようになる pure<*>のための別々のクラスで、よりきめの細かい部分にダウン Applicativeを壊すよりきめの細かい型クラス階層を持つことができ

制約。おそらく、これを行うにはハスケルで十分ではなかったでしょう。

他のエコシステムでは、より細かいタイプクラス階層が選択されています(Scalaのcatsまたはscalazライブラリを参照)。私は個人的にはこのような区別は時折便利だが圧倒的にそうではないと思う。

あなたのやり方が分かっていれば、途中で効果を引き出すことができますが、必ずしも元の構造を回復することはできません。したがって、なぜsequenceA_Foldableにあるのですか?それは厳密にはsequenceAよりも強力ではありません。

関連する問題