实现`traverse`和`sequenceA`

时间:2015-12-25 05:04:52

标签: haskell

我试图自己实施traversesequenceA

traverse'方式sequenceA实施traverse' :: (Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b) traverse' f x = sequenceA' $ fmap f x

sequenceA

但是,我坚持实施sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a) sequenceA' x = foldr (\a _ -> fmap helper a) (error "...") x

b

我使用error "..."b)的占位符 - 我不确定如何在给定这些类型的情况下创建helper :: (Functor t, Foldable t) => a -> t a helper x = error "TODO"

helper

另外,我使用error函数来获取此代码以进行类型检查。但是,再一次,这只是一个sequenceA电话。 请给我一些关于如何一般性地实施breaks的提示。

1 个答案:

答案 0 :(得分:8)

假设:

traverse' :: (Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse' a2fb ta = sequenceA' (fmap a2fb ta)

sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' tfa = _

洞的理想用途!我们给所有参数命名(不需要去点免费,让我们的生活变得非常困难)并在定义应该是一个洞。这会产生:

src/Main.hs:8:14: Found hole ‘_’ with type: f (t a) …

我们现在转向一个返回f (t a)之类的函数。幸运的是,traverse'确实如此,现在我们可以改进我们的洞:

sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' tfa = traverse _ _

src/Main.hs:8:27: Found hole ‘_’ with type: a0 -> f a …
src/Main.hs:8:29: Found hole ‘_’ with type: t a0 …

第一个看起来很混乱,但我们知道第二个符合t a0的东西,即tfa。插头和突突:

sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' tfa = traverse _ tfa

src/Main.hs:8:27: Found hole ‘_’ with type: f a -> f a …

好吧,我们知道带有该签名的函数,那就是id。所以我们的最终答案是:

traverse' :: (Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse' a2fb ta = sequenceA' (fmap a2fb ta)

sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' tfa = traverse id tfa

我们现在可以变得年轻,狂野,无拘无束(-ish):

traverse' :: (Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse' a2fb = sequenceA' . fmap a2fb

sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' = traverse id

Which matches the definitions in Prelude.〜holes~