Monad of Nothing不适用于猫

问题描述:

我遇到cats/monads /理解问题。 请考虑下面的代码片段:Monad of Nothing不适用于猫

import cats._ 
import cats.implicits._ 

final case class My[T]() 
implicit val monadMy: Monad[My] = new Monad[My] { ... } 

// this compiles 
def test11[A, B](m: My[A], f: A => B): My[B] = m.map(f) 
// this fails: value map is not a member of My[Nothing] 
def test12[B](m: My[Nothing], f: Nothing => B): My[B] = m.map(f) 

// this compiles 
def test21[A, B](m: My[A], f: A => My[B]): My[B] = m.flatMap(f) 
// this fails: type mismatch; 
// [error] found : A => My[Nothing] 
// [error] required: A => My[B] 
def test22[A](m: My[A], f: A => My[Nothing]): My[Nothing] = m.flatMap(f) 

我意识到test12可能看起来很奇怪但它将使for语法:

for (...; nothing <- My[Nothing]()) yield nothing 

test22显示失​​败使得cats.monad不能用于我的情况。 是否monad的Nothing违反monad法律?

请协助,我希望能够flatMapM[Nothing]

在此先感谢。

更新,如果我做了My协变,但不幸的是原来我用cats.Free,我没有获得这个最小的代码片段将编译。

UPDATE还有一个解决方法是使用多态函数,我到处都用Nothing,即使用test11无处不在,我需要test12,但同样,我想明白为什么M[Nothing]行为是比任何其他类型的不同。

UPDATE顺便说一句,如果我将Nothing更改为例如它会编译。所以,看起来这是设计。但为什么?

UPDATE另一个解决方法:切换到scalaz

UPDATE看起来像问题纯粹与scala有关。

UPDATE解决方法:声明未定义type Bottom <: Nothing并改为使用它。

+3

心灵请问切换是非常有用的创建?你想达到什么目的? –

+0

例如列表monad失败,如果发生了这种情况,会将所有内容都变为空列表,那就是'val failure:List [Nothing] = Nil'。当然我可以做'def failure [T]:List [T] = Nil',它可以工作,但... –

+0

list monad的失败是什么意思?不知道我明白。 –

试着制作My协变在T。然后代码编译。

final case class My[+T]() 

随着不变T这是

Information:27.09.17 15:55 - Compilation completed with 2 errors and 0 warnings in 2s 804ms 
/home/dmitin/Projects/myproject/src/main/scala/App.scala 

Information:(19, 59) toFunctorOps is not a valid implicit value for m.type => ?{def map: ?} because: 
type mismatch; 
found : m.type (with underlying type App.My[Nothing]) 
required: App.My[A] 
Note: Nothing <: A, but class My is invariant in type T. 
You may wish to define T as +T instead. (SLS 4.5) 
    def test12[B](m: My[Nothing], f: Nothing => B): My[B] = m.map(f) 

Error:(19, 61) value map is not a member of App.My[Nothing] 
    def test12[B](m: My[Nothing], f: Nothing => B): My[B] = m.map(f) 

Error:(26, 73) type mismatch; 
found : A => App.My[Nothing] 
required: A => App.My[B] 
    def test22[A](m: My[A], f: A => My[Nothing]): My[Nothing] = m.flatMap(f) 

有时它为什么你需要Nothing`的`一个单子,这是一种你不能scalacOptions += "-Xlog-implicits"

+1

这将有所帮助,但我无法使它变得协变,因为最初我使用'cats.Free',它不是协变的,而是它的第二个参数。我会更新我的问题。 –