Haskell “什么是”呢;独特方法“;除了可折叠外,还具有可遍历性?
是的超类,类似于Haskell “什么是”呢;独特方法“;除了可折叠外,还具有可遍历性?,haskell,containers,fold,traversable,Haskell,Containers,Fold,Traversable,是的超类,类似于Functor是Applicative和Monad的超类 与Monad的情况类似,基本上可以实现fmap liftM :: Monad m => (a->b) -> m a -> m b liftM f q = return . f =<< q foldLiftT :: (Traversable t, Monoid m) => (a -> m) -> t a -> m foldLiftT f = fst . trave
Functor
是Applicative
和Monad
的超类
与Monad
的情况类似,基本上可以实现fmap
liftM :: Monad m => (a->b) -> m a -> m b
liftM f q = return . f =<< q
foldLiftT :: (Traversable t, Monoid m) => (a -> m) -> t a -> m
foldLiftT f = fst . traverse (f >>> \x -> (x,x))
-- or: . sequenceA . fmap (f >>> \x -> (x, x))
使用monoidm=>(,)m
monad。因此,超类和方法的组合在这两种情况下都有一定的冗余
对于monad,可以认为类型类的“更好”定义是(我将跳过applicative/monoidal)
至少在范畴理论中是这样的。在不使用函子
超类的情况下,此定义不允许liftM
,因此它没有这种冗余
可遍历类是否可以进行类似的转换
澄清一下:我想要的是一个重新定义,我们称之为
class (Functor t, Foldable t) => Traversable t where
skim :: ???
这样我们就可以使实际的遍历方法成为顶级函数
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
但不可能作出一般性的决定
instance (Traversable t) => Foldable t where
foldMap = ... skim ...
data T
instance Traversable T where
skim = ...
我问这个不是因为我需要这个来做一些特别的事情;这是一个概念性问题,以便更好地理解可折叠
和可遍历
之间的区别。再次类似于Monad
vsFunctor
:而>=
对于日常Haskell编程来说要比join
方便得多(因为您通常需要fmap
和join
的精确组合),后者使我们更容易理解单子的含义。可折叠的
是对函子的
,正如可遍历的
是对单子的
,也就是说,可折叠的
和函子
是对单子
和可遍历的
的超类(对所有应用程序/单子进行模化)
事实上,这已经在代码中了
instance Foldable f => Traversable f where
...
所以,还不清楚还有什么需要Foldable
的特点是toList::Foldable f=>fa->[a]
,而Traversable
最终取决于不仅能够像toList
那样将内容抽象为列表,而且能够提取形状
shape :: Functor f => f a -> f ()
shape = fmap (const ())
然后重新组合它们
combine :: Traversable f => f () -> [a] -> Maybe (f a)
combine f_ = evalStateT (traverse pop f_) where
pop :: StateT [a] Maybe a
pop = do x <- get
case x of
[] = empty
(a:as) = set as >> return a
combine::Traversable f=>f()->[a]->Maybe(fa)
联合收割机f_u2;=evalStateT(遍历弹出f_2;),其中
例如:StateT[a]可能是
pop=do x>返回一个
这取决于遍历
有关此属性的详细信息,请参见。超级手波浪,因为它太晚了,但是可遍历的
比可折叠的具有更多的功能,这是一种重建原始结构的方法。例如,使用列表:
module MyTraverse where
import Data.Foldable
import Data.Traversable
import Control.Applicative
import Data.Monoid
data ListRec f x = ListRec
{ el :: f (Endo [x])
}
instance Applicative f => Monoid (ListRec f x) where
mempty = ListRec (pure mempty)
mappend (ListRec l) (ListRec r) =
ListRec (mappend <$> l <*> r)
toM :: Functor f => f b -> ListRec f b
toM this = ListRec $ (Endo . (:)) <$> this
fromM :: Functor f => ListRec f b -> f [b]
fromM (ListRec l) = flip appEndo [] <$> l
myTraverse :: Applicative f => (a-> f b) -> [a] -> f [b]
myTraverse f xs = fromM $ foldMap (toM . f) xs
这似乎与Foldable
有很大的重叠,但我认为当试图将路径与其组成值关联时,这是不可避免的。不同的方法是遍历
。您不能用可折叠
实现这一点。当然不能,但您可以用遍历
实现可折叠
。。。。这就是为什么Foldable
是Traversable
的超类。一个超类应该可以用子类来实现。我认为@leftaroundabout是在问一个等价的问题:你能定义一个类TraversableMinusFoldable
,这样`class(Foldable t,TraversableMinusFoldable t)=>TraversableT其中`没有新函数,但现有函数是兼容的。如中所示,您是否可以定义遍历
,而不参考可折叠
中的任何内容。但即使这是个问题,我也不认为这不是研究现状的正确方法。老蒙纳德一团糟,最好忘了它:-)@先生:差不多是这样,但不完全是这样。我感兴趣的是你能给出的可遍历的方法的“最弱的可能签名”,因此实际使用实际上需要超类可折叠的。目前,您基本上可以省略历史Monad
中的超类,正如您所说,这并不好。因此,如果combine
是可遍历的的唯一方法,是否能够用它来定义travel
/sequenceA
?我可能会说,对函子来说,可折叠就像对应用程序来说,可遍历一样。@leftaroundaounda试试看,如果卡住了就发布:-)好的,这样我们就可以在fmap中实现sequenceA q=let{structure=fmap(const())q;values=toList q}(fromJust.combine结构)$Prelude.sequence值
。如果我们需要combine(fmap(const())q)(toList q)
始终“有效”的公理,我想这就足够了这似乎回答了我的问题,尽管正如你所说的combine
看起来并不优雅。如果我们有依赖类型,我们可以编写combine::Traversable f=>πx:f().Vec a(长度x)->f a
。我们可以在不使用依赖类型的情况下创建可遍历类这一事实有点令人惊讶。这可能与它使用应用函子的辅助类并假设它们遵循它们的规律有关。
module MyTraverse where
import Data.Foldable
import Data.Traversable
import Control.Applicative
import Data.Monoid
data ListRec f x = ListRec
{ el :: f (Endo [x])
}
instance Applicative f => Monoid (ListRec f x) where
mempty = ListRec (pure mempty)
mappend (ListRec l) (ListRec r) =
ListRec (mappend <$> l <*> r)
toM :: Functor f => f b -> ListRec f b
toM this = ListRec $ (Endo . (:)) <$> this
fromM :: Functor f => ListRec f b -> f [b]
fromM (ListRec l) = flip appEndo [] <$> l
myTraverse :: Applicative f => (a-> f b) -> [a] -> f [b]
myTraverse f xs = fromM $ foldMap (toM . f) xs
class Traversed t where
type Path t :: *
annotate :: t a -> [(Path t, a)]
fromKeyed :: [(Path t, a)] -> t a