在开始阅读之前:这个问题不是关于理解monad,而是关于识别Java类型系统的限制,这会限制Monad接口的声明.
在我的努力去理解单子我读这个由埃里克利珀SO-答案上询问单子简单的解释问题.在那里,他还列出了可以在monad上执行的操作:
- 有一种方法可以获取未放大类型的值并将其转换为放大类型的值.
- 有一种方法可以将非放大类型的操作转换为符合之前提到的功能组合规则的放大类型的操作
- 通常有一种方法可以将未放大的类型从放大类型中取出.(对于monad而言,这最后一点并非绝对必要,但通常情况下存在这样的操作.)
在阅读了关于monads的更多信息后,我将第一个操作识别为return函数,将第二个操作识别为bind函数.我无法找到第三个操作的常用名称,因此我将其称为unbox函数.
为了更好地理解monad,我继续尝试Monad用Java 声明一个通用接口.为此,我首先看了上面三个函数的签名.对于Monad M,它看起来像这样:
return :: T1 -> M<T1>
bind :: M<T1> -> (T1 -> M<T2>) -> M<T2>
unbox :: M<T1> -> T1
Run Code Online (Sandbox Code Playgroud)
该return函数不在实例上执行M,因此它不属于该Monad接口.相反,它将实现为构造函数或工厂方法.
此外,我现在省略了unbox接口声明中的函数,因为它不是必需的.对于接口的不同实现,将具有该功能的不同实现.
因此,Monad接口仅包含该bind功能.
让我们尝试声明接口:
public interface Monad {
Monad bind();
}
Run Code Online (Sandbox Code Playgroud)
有两个缺点:
bind函数应返回具体实现,但它只返回接口类型.这是一个问题,因为我们在具体的子类型上声明了unbox操作.我将此称为问题1.bind函数应该将函数检索为参数.我们稍后会解决这个问题.这解决了问题1:如果我对monads的理解是正确的,那么bind函数总是会返回一个与调用它的monad具有相同具体类型的新monad.所以,如果我有一个Monad被调用的接口的实现M …