我遇到了一个结构,它看起来像具有单边逆元和一些附加属性的单子。我不确定这个结构的哪些属性是必不可少的,哪些是偶然的,所以我将在我的描述中遵循一个简单的例子。
我有一个基本类型a
,它由排序的字符串(例如"aacdee"
但不是"abca"
)和来自的 monadM
组成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
which 接受一个字符串列表,将它们连接起来并对结果进行排序。这是 的左逆pure
,即extract . pure = id
on 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", "c", "def"] = ["ab", "", "f"]
。
所有这一切背后的想法是,一个人可以对M a
多种.f
extend f
extend f = pure f
我extend
不会满足comonad公理,但至少会满足以下条件(或非常相似的条件,我不完全确定关联性):
(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)
,即关联性,或者可能是它的较弱形式。
我的问题。这是一个众所周知的结构吗?它有什么特别有趣的特性吗?