Any two applicative functors can be composed and yield another applicative functor. But this does not work with monads. A composition of two monads is not always a monad. For example, a composition of State and List monads (in any order) is not a monad.
此外,一个人一般不能合并两个单子,无论是通过合成或任何其他方法。目前还没有已知的算法或程序将任何两个单子 M、 N组合成一个更大的、合法的单子 T,这样你就可以通过单子态注入 M ~> T和 N ~> T,并满足合理的非简并定律(例如,保证 T不仅仅是一个单位类型,抛弃来自 M和 N的所有效应)。
可以为特定的 M和 N定义一个合适的 T,例如 M = Maybe和 N = State s等等。但是如何定义在单子 M和 N中参数化工作的 T是未知的。函数复合和更复杂的构造都不能正常工作。
结合单子 M和 N的一种方法是首先定义副产物 C a = Either (M a) (N a)。这个 C将是一个函子,但通常不是单子。然后在函数 C上构造一个空单子(Free C)。结果是一个单子,能够代表的影响 M和 N结合。然而,它是一个大得多的单子,也可以代表其他效应; 它比仅仅 M和 N效应的组合大得多。此外,自由单子将需要“运行”或“解释”,以提取任何结果(并且单子定律只有在“运行”之后才能得到保证)。由于空闲单子可能会在“运行”之前在内存中构建非常大的结构,因此将会有运行时损失和内存大小损失。如果这些缺点不是很明显,那么免费单子就是一条出路。
至少有4种不同类型的单子,其变压器构造完全不同,但有规律的方式(组成-内部,组成-外部,基于辅助单子,产品单子)。其他一些单子不属于这些“常规”类中的任何一个,并且以某种方式定义了转换器“ ad hoc”。
Distributive laws exist only for composed monads. It is misleading to think that any two monads M, N for which one can define some function M (N a) -> N (M a) will compose. In addition to defining a function with this type signature, one needs to prove that certain laws hold. In many cases, these laws do not hold.
有些单子甚至有两个不等效的变换器,一个定义为“常规”变换器,一个定义为“特别”变换器。一个简单的例子是单位单子 Id a = a; 它具有常规变压器 IdT m = m(“组合”)和不规则的“特别”变压器: IdT2 m a = forall r. (a -> m r) -> m r(m上的共密度单子)。
一个更复杂的例子是“ selector monad”: Sel q a = (a -> q) -> a。这里 q是一个固定的类型,而 a是单子 Sel q的主要类型参数。这个单子有两个变压器: SelT1 m a = (m a -> q) -> m a(内部组合)和 SelT2 m a = (a -> m q) -> m a(特别)。