Scala for-comprehension with Option 和 Some,由 ReaderT 包装
Scala for-comprehension with Option and Some, wrapped by ReaderT
这是一个运行良好的示例:
import cats.data.ReaderT
import cats.instances.option._
...
def f1:ReaderT[Option, Service, Int] =
ReaderT(service => for {
res <- Some(10)
} yield res )
这里是一个没有编译的例子:
def f2:ReaderT[Option, Service, Int] =
for {
res <- ReaderT((_:Service) => Some(10))
} yield res
我收到以下错误:
Error:(53, 11) could not find implicit value for parameter F:
cats.Functor[Some]
res <- ReaderT((:Service) => Some(10)) Error:(53, 11) not enough arguments for method map: (implicit F:
cats.Functor[Some])cats.data.Kleisli[Some,com.savdev.Service,Int].
Unspecified value parameter F.
res <- ReaderT((:Service) => Some(10))
要修复第二个示例中的错误,我必须 return 而不是 Some
,而是 Option
,它是 Some
:[=20= 的父级]
def f2:ReaderT[Option, Service, Int] =
for {
res <- ReaderT((_:Service) => Option(10))
} yield res
你能解释一下吗?为什么在第一个例子中 returning Some
,而不是 Option
,工作正常。为什么在第二个例子中,returning Some
没有被编译? Scala 编译器是否有编译案例的选项,如第二个示例?或其他解决方案。
尝试
import cats.syntax.option._
def f2: ReaderT[Option, Service, Int] =
for {
res <- ReaderT((_: Service) => 10.some)
} yield res
最好使用x.some
和none
(或none[X]
)而不是Some(x)
和None
。它们的类型为 Option[X]
而不是 Some[X]
和 None.type
。这有时可以改进类型推断。实际上 Option
是 Functor
的一个实例,而不是 Some
.
在https://blog.softwaremill.com/9-tips-about-using-cats-in-scala-you-might-want-to-know-e1bafd365f88
中查看"Extension method constructors"
在第一种情况下,您很幸运能够正确推断出类型。
在第一种情况下,它直接在 Some
上调用 map
,这是 return 和 Option
已知的(带有子类的普通多态性Some
of Option
), 然后继续寻找 Functor[Option]
.
在第二种情况下,你的函数的return类型被推断为Some[Int]
,编译器试图找到一个Functor[Some]
类型类的实例为了调用 Reader
上的方法(类型类 Functor
的临时多态性),但这失败了,因为 Some
.
[=40 没有函子=]
主要问题是 Some
不仅仅是 Option
类型实例的构造函数(例如 Haskell),但它实际上是类型 Some
(大部分无用)实例的构造函数,有时会搞乱类型推断/隐式解析。
如果要强制结果类型为 Option[Int]
,请使用 Option(10)
构造 Some
或 Option.empty
构造 None
。
这是一个运行良好的示例:
import cats.data.ReaderT
import cats.instances.option._
...
def f1:ReaderT[Option, Service, Int] =
ReaderT(service => for {
res <- Some(10)
} yield res )
这里是一个没有编译的例子:
def f2:ReaderT[Option, Service, Int] =
for {
res <- ReaderT((_:Service) => Some(10))
} yield res
我收到以下错误:
Error:(53, 11) could not find implicit value for parameter F: cats.Functor[Some] res <- ReaderT((:Service) => Some(10)) Error:(53, 11) not enough arguments for method map: (implicit F: cats.Functor[Some])cats.data.Kleisli[Some,com.savdev.Service,Int]. Unspecified value parameter F. res <- ReaderT((:Service) => Some(10))
要修复第二个示例中的错误,我必须 return 而不是 Some
,而是 Option
,它是 Some
:[=20= 的父级]
def f2:ReaderT[Option, Service, Int] =
for {
res <- ReaderT((_:Service) => Option(10))
} yield res
你能解释一下吗?为什么在第一个例子中 returning Some
,而不是 Option
,工作正常。为什么在第二个例子中,returning Some
没有被编译? Scala 编译器是否有编译案例的选项,如第二个示例?或其他解决方案。
尝试
import cats.syntax.option._
def f2: ReaderT[Option, Service, Int] =
for {
res <- ReaderT((_: Service) => 10.some)
} yield res
最好使用x.some
和none
(或none[X]
)而不是Some(x)
和None
。它们的类型为 Option[X]
而不是 Some[X]
和 None.type
。这有时可以改进类型推断。实际上 Option
是 Functor
的一个实例,而不是 Some
.
在https://blog.softwaremill.com/9-tips-about-using-cats-in-scala-you-might-want-to-know-e1bafd365f88
中查看"Extension method constructors"在第一种情况下,您很幸运能够正确推断出类型。
在第一种情况下,它直接在
Some
上调用map
,这是 return 和Option
已知的(带有子类的普通多态性Some
ofOption
), 然后继续寻找Functor[Option]
.在第二种情况下,你的函数的return类型被推断为
[=40 没有函子=]Some[Int]
,编译器试图找到一个Functor[Some]
类型类的实例为了调用Reader
上的方法(类型类Functor
的临时多态性),但这失败了,因为Some
.
主要问题是 Some
不仅仅是 Option
类型实例的构造函数(例如 Haskell),但它实际上是类型 Some
(大部分无用)实例的构造函数,有时会搞乱类型推断/隐式解析。
如果要强制结果类型为 Option[Int]
,请使用 Option(10)
构造 Some
或 Option.empty
构造 None
。