使用するとき、Data.Traversable
私は頻繁に次のようなコードを必要とします
import Control.Applicative (Applicative,(<*>),pure)
import Data.Traversable (Traversable,traverse,sequenceA)
import Control.Monad.State (state,runState)
traverseF :: Traversable t => ((a,s) -> (b,s)) -> (t a, s) -> (t b, s)
traverseF f (t,s) = runState (traverse (state.curry f) t) s
構造を横断し、何らかの状態によって駆動される新しい構造を構築します。そして、型署名パターンに気づき、次のように一般化できると信じています
fmapInner :: (Applicative f,Traversable t) => (f a -> f b) -> f (t a) -> f (t b)
fmapInner f t = ???
しかし、 、 、、およびだけtraverse
で はこれを実装できません。たぶん、より強い型クラスの制約が必要ですか? ここは絶対に必要ですか?sequenceA
fmap
<*>
pure
Monad
アップデート
具体的には、適用される直観の法則の一部で機能fmapInner
する aを定義できるかどうかを知りたいです(法則がどうあるべきかはまだわかりません) 。したがって、 for s の実装は簡単です。f
Traversable t
f
Monad
Monad
--Monad m implies Applicative m but we still
-- have to say it unless we use mapM instead
fmapInner :: (Monad m,Traversable t) => (m a -> m b) -> m (t a) -> m (t b)
fmapInner f t = t >>= Data.Traversable.mapM (\a -> f (return a))
アップデート
素晴らしい答えをありがとう。私は自分traverseF
がちょうどであることがわかりました
import Data.Traversable (mapAccumL)
traverseF1 :: Traversable t => ((a, b) -> (a, c)) -> (a, t b) -> (a, t c)
traverseF1 =uncurry.mapAccumL.curry
Monad.State を明示的に使用せずに、すべてのペアを反転させます。以前はそうだと思っていましたmapAccumR
が、実際にはmapAccumL
のように動作しtraverseF
ます。