这是一种什么样的结构? 具有部分逆但不是共子的单子

问题描述

我遇到了一个结构,它看起来像一个单子,具有单边逆和一些附加属性。我不确定这个结构的哪些属性是必不可少的,哪些是偶然的,所以我将在我的描述中遵循一个简单的例子。

我有一个基本类型 a,它由排序的字符串(例如 "aacdee" 但不是 "abca")和来自 M 的 monad a 组成,它是只是 List monad:M a 是列表 排序的字符串。这个 monad 定义了 pure: a -> M afmap: (a -> a) -> M a -> M abind: (a -> M a) -> M a -> M a

现在我定义了 extract: M a -> a,它接受​​一个字符串列表,将它们连接起来并对结果进行排序。这是 pure 的左逆,即 extract . pure = id 上的 a,但不是右逆。

我还想以这样的方式定义 extend: (M a -> a) -> M a -> M a,即 extract . (extend f) = f 代表所有 f: M a -> a

虽然可以定义 extend f = pure . f,但我不想这样做。 例如,如果 f 是用字母表中的下一个字符替换每个字符、连接和排序的函数,我希望 extend f 只用下一个字符替换每个字符。同样,如果 f 从第一个字符串中删除所有“a”,从第二个字符串中删除所有“b”,等等。

一个不那么简单的例子,以f作为取第一个字符串的函数,然后如果第二个字符串比第一个长,则用第二个的最后一个元素扩展第一个字符串,依此类推。例如,f ["ab","c","def"] = "abf"在这种情况下,我希望 extend f 只适合每个字符串,只留下对结果有贡献的字母,在示例 (extend f) ["ab","def"] = ["ab","","f"] 中。

这一切背后的想法是,在 M a 中可以对多种 f 进行并行优化,我想将 extend f 定义为针对许多特定情况的优化实现,仅在未优化的情况下回退到 extend f = pure f

我的 extend 不会满足共子公理,但至少会满足以下条件(或非常相似的条件,我不完全确定结合性):

  • (extend f) . pure = pure . f . pure,即在单个字符串上 fextend f 本质上是相同的,
  • extend (extract . (fmap h)) = fmap h,即如果 g = extract . (fmap h) 分别作用于每个字符串,那么 extend g 也一样,
  • (extend f) . (extend g) = extend (f . pure . g),即结合性,或者它的弱形式。

我的问题。这是一个众所周知的结构吗?它有什么特别有趣的特性吗?

解决方法

单独看extract,我们看到extract . pure = id。我们还看到 extract . join = extract . fmap extract。这使得 extract 成为 algebra over the [] monad

特别是,[] monad 上的代数完全对应于幺半群(范畴论解释:健忘函子 Monoids -> Sets 是一元的,它的左伴随是 [],所以幺半群正好是[] 函子上的代数)。所以 extract 定义了 a 上的幺半群,具有明显的单位和组合定律。

至于 extend,我认为您没有正确的类型。这是因为 extend f :: M a -> M a,所以 extend f 不能作为 extract 的参数,因此 extract (extend f) 不进行类型检查。也许一旦你解决了这个问题,就会更容易理解这里发生了什么。