问题描述
我是Scala的新手,所以答案可能很明显。
在Scala FP in Scala中通过FP时,我注意到unit
方法放在伴随对象上,而不是放在类上,因此我尝试将其移到类上。
它导致了我不理解的错误,有人可以向我解释吗?
在类上取消对unit
方法的注释并在伴随对象上将其注释掉时,将导致此错误:
那是为什么?
import State._
case class State[S,A](run: S => (A,S)) {
def map[B](f: A => B): State[S,B] =
flatMap(a => unit(f(a)))
def map2[B,C](sb: State[S,B])(f: (A,B) => C): State[S,C] =
flatMap(a => sb.map(b => f(a,b)))
def flatMap[B](f: A => State[S,B]): State[S,B] = State(s => {
val (a,s1) = run(s)
f(a).run(s1)
})
// This results in an error here:
// flatMap(a => unit(f(a))) ... required A,found B
// def unit(a: A): State[S,A] = State(s => (a,s)) // ERROR
}
object State {
// Comment out when uncommenting above
def unit[S,A](a: A): State[S,s))
}
解决方法
该错误解释了问题所在,但这是故障所在。
以map
开头:
def map[B](f: A => B): State[S,B] =
flatMap(a => unit(f(a)))
由于f
返回的未知类型为B
,因此正在调用值为unit
类型的B
。但是unit
被定义为采用A
,它是case class
的类型参数:
def unit(a: A): State[S,A] = State(s => (a,s))
由于B
可能不是A
,因此编译器会抱怨。
伴随对象内部的代码不同:
object State {
def unit[T,U](a: U): State[T,U] = State(s => (a,s))
}
我已经重命名了类型参数,以明确它们现在与case类的类型参数无关。而且,由于unit
的参数类型可以是任何类型的U
,因此可以将B
类型的值传递给它。
要在unit
中固定case class
的定义,请为其提供类型参数:
case class State[S,A](run: S => (A,S)) {
// ...
def unit[T](a: T): State[S,T] = State(s => (a,s))
}