我遇到了一个看起来像是单子但具有单侧逆元和其他属性的结构。我不确定这个结构的哪些属性是必要的,哪些是偶然的,因此在我的描述中我将遵循一个简单的例子。我的基本类型是
a
,由排序字符串组成(例如"aacdee"
但不包括"abca"
),以及从a
到List单子M a
。这个单子定义了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", "c", "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)
,即结合律,或者它的一个较弱形式。
我的问题。这是一种众所周知的结构吗? 它有任何奇特有趣的属性吗?
M a
中的x
,extract ((extend f) x) = f x
。我现在已经在问题中添加了函数组合。 - AndreA