问题描述
我遇到了一个结构,它看起来像一个单子,具有单边逆和一些附加属性。我不确定这个结构的哪些属性是必不可少的,哪些是偶然的,所以我将在我的描述中遵循一个简单的例子。
我有一个基本类型 a
,它由排序的字符串(例如 "aacdee"
但不是 "abca"
)和来自 M
的 monad a
组成,它是只是 List monad:M a
是列表
排序的字符串。这个 monad 定义了 pure: a -> M a
、fmap: (a -> a) -> M a -> M a
和 bind: (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
,即在单个字符串上f
和extend 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)
不进行类型检查。也许一旦你解决了这个问题,就会更容易理解这里发生了什么。