traverse
default定義として、よくtraverseが定義される
定義
code:hs
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse f = sequenceA . fmap f
データ構造tと計算コンテナfを入れ替えている
a -> f bにt aを適用するとt (f b)になるはずだが、
結果は、データ構造tと計算コンテナfを入れ替えて、f (t b)になる
上記の定義をListに対して書き換えてみると以下のように書ける
code:hs
traverse f [] = pure []
traverse f (x:xs) = (:) <$> f x <*> traverse f xs
いくつかの型での定義を見る
List
code:hs
traverse :: Applicative f => (a -> f b) -> a -> f b traverse f [] = pure []
traverse f (x:xs) = (:) <$> f x <*> traverse f xs
実際はfoldrを使ってもっとスマートに定義されているが同じ意味
code:hs
traverse f = foldr (\x ys -> (:) <$> f x <*> ys) (pure [])
Maybe
code:hs
traverse :: Applicative f => (t -> f a) -> Maybe t -> f (Maybe a)
traverse _ Nothing = pure Nothing
traverse f (Just x) = Just <$> f x
Either
code:hs
traverse :: Applicative f => (t -> f b) -> Either a t -> f (Either a b)
traverse _ (Left x) = pure (Left x)
traverse f (Right y) = Right <$> f y
どれも以下のような感じで定義されていることがわかる
code:hs
traverse f ... = pure データ構成子
traverse f ... = データ構成子 <$> f x1 (または traverse f xs1)
<*> f x2 (または traverse f xs2)
...
<*> f xn (または traverse f xsn)
使用例
なんかしょうもない例しか思いつけないが
与えられた[Int]の要素が全部奇数ならばJust [Int]、一つでも偶数があればNothingを返す
code:hs
f :: (Traversable t, Integral b) => t b -> Maybe (t b)
f = traverse $ \n -> if odd n then Just n else Nothing
参考