最近我一直在“将一切提炼为基础”,并且我一直无法找到关于如何定义 Traversable 类型类的明确的理论原因,只有“能够遍历是有用的”的实际原因在应用余代数上,很多数据类型都可以做到这一点”以及很多提示。
我知道有一个适用的“家族”,如https://duplode.github.io/posts/divisible-and-the-monoidal-quartet.html所描述。
我还知道,虽然 Traversable 遍历是应用性余代数,但“semigroupoids”中的 Traversable1 类型类描述了应用性余代数,“distributive”中的 Distributive 类型类描述了函子代数。
此外,我知道 Foldable、Foldable1 和理论折叠家族成员描述了可以使用幺半群、半群和相应的幺半群家族成员(例如岩浆(用于折叠为二叉树)和每个的交换版本)折叠的数据类型(用于折叠为每个的无序版本)。
因此,由于 Traversable 是 Foldable 的子类,我假设它本质上是幺半群的,同样,我假设 Traversable1 本质上是半群的,而 Distributive 本质上是共单体的(如“分布”包中的描述中所述)。
这感觉像是正确的轨道,但是 Applicative 和 Apply 从哪里来呢?有岩浆版本和交换版本吗?在具有非平凡共类群的范畴中是否存在分布式族?
本质上,我的问题是“这些类型类是否存在,它们是什么?如果不存在,为什么不存在?”:
class FoldableMagma t => TraversableMagma t where
traverseMagma :: ??? f => (a -> f b) -> (t a -> f (t b))
class FoldableCommute t => TraversableCommute t where
traverseCommute :: ??? f => (a -> f b) -> (t a -> f (t b))
class Foldable t …Run Code Online (Sandbox Code Playgroud) a -> m bfrom to函数m (a -> b)在编程中很少出现,但可以在 Reader monad 中制作。以下代码是暂定的实现。这样的图书馆存在吗?
class Monad m => MonadShift m where
shift :: (a -> m b) -> m (a -> b)
instance MonadShift Identity where
shift f = Identity (\x -> runIdentity (f x))
instance MonadShift m => MonadShift (ReaderT r m) where
shift f = ReaderT (\r -> shift (\x -> runReaderT (f x) r))
Run Code Online (Sandbox Code Playgroud) 我有代码(实际上是在C#中,但是这个问题与C#没有任何关系,所以我会谈到我在Haskell中说的所有类型)我在里面工作Either a b.然后我bind有一个带有签名的函数,在Haskell中说的是b -> (c, d),之后我想拉到c外面并在左边的情况下默认它,即我想要的(c, Either a d).现在这种模式多次出现在我写的一个特定服务中,所以我提出了一种方法来实现它.然而,每当我在没有理解正确的理论基础的情况下"弥补"这样的方法时,它就会让我感到困扰.换句话说,我们在这里处理什么抽象?
在一些F#代码中我遇到了类似的情况,其中我和我的对方都被颠倒了:(a, b) -> (b -> Either c d) -> Either c (a, d).我问朋友什么,这是他使我对穿越这使得即使我不得不在F#惊人,单态实现我很开心,由于缺乏类型类.(我希望我可以将我F1的Visual Studio 重新映射到Hackage;它是我编写.NET代码的主要资源之一).但问题是遍历是:
class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
Run Code Online (Sandbox Code Playgroud)
这意味着当你开始有一对,并希望"绑定"的要么是它的伟大工程,但不工作,当你开始用,因为对是不是一个非此即彼,并希望有一对就结了,应用型.
然而,我更多地考虑了我的第一个案例,那个不是traverse,并且意识到" c在左案例中违约"只能通过左侧案例的映射来完成,这会将问题改为具有这种形状:Either (c, a) (c, d) …
我正在尝试更新使用Text.Parsec.Expr的秒差距解析器。我正在尝试(这可能是不明智的,但看起来应该是实用的)将 DSL 验证的一部分构建到解析器中。但我很难让它与类型一起工作,它的主体需要是一个生成函数的解析器buildExpressionParserOperator。
data Location = Location { owners :: PartySet, source :: SourcePos } deriving (Eq, Ord, Show)\ntype Located = (,) Location\ntype Parser = Parsec String (Map Variable PartySet)\n\n-- Pair a parsed thing with it\'s position in the source file\npositioned :: Parser a -> Parser (SourcePos, a)\npositioned p = do source <- getPosition\n (source,) <$> p\n\nchooseOf :: (TokenParser st -> t -> Parsec.Parser a) -> [t] -> Parser (SourcePos, a)\nchooseOf …Run Code Online (Sandbox Code Playgroud)