Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell “什么是”呢;独特方法“;除了可折叠外,还具有可遍历性?_Haskell_Containers_Fold_Traversable - Fatal编程技术网

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
vs
Functor
:而
>=
对于日常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