我已经和ADT函子基本上是一个包装过Function1
:斯卡拉:如何使用多类型参数特征
case class Abstract[M[_], A, B](f:M[A] => M[B]) {
def fn: M[A] => M[B] = { case x: M[A] => f(x) }
}
我要地图了这些,所以我定义了一个函子,像这样:
trait AbstractAPI[E] {
type AbsO[T] = Abstract[List, E, T]
// type AbsO[T] = Abstract[List, _, T] => does not work (?)
implicit val abstractO: Functor[AbsO] = new Functor[AbsO] {
def map[A, B](fa: AbsO[A])(f: A => B): AbsO[B] = {
new Abstract(fa.fn andThen { x: List[A] => x.map{ y => f(y) } })
}
}
}
现在,实际上映射了一个抽象的,我需要AbstractAPI[Int]
,像
case object IntAbstractAPI extends AbstractAPI[Int]
object A {
import IntAbstractAPI._
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
val hey = (new Abstract(f)).map{ x => x.toInt }
}
或
object A extends AbstractAPI[Int] {
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
// FINALLY!
val res = (new Abstract(f)).map{ x => x.toInt }.map{ _.toFloat + 10f }
// Abstract[List, Int, Float] = Abstract(<function1>)
}
然而,在这种模式中,我不得不定义每个可能的E
情况的对象。这里是我的问题:
- 这是使用Functors的正确方法吗?
- 我如何可以自动的情况下创建对象的每一个可能的
E
(或使编译器推断呢?)
编辑1: 进一步澄清:上述实施工作,但是这一次不会:
object A extends AbstractAPI {
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
val res = (new Abstract(f)).map{ x => x.toInt }.map{ _.toFloat + 10f }
// Abstract[List, Int, Float] = Abstract(<function1>)
}
给出编译错误:
value map is not a member of Abstract[List,Int,String]
我想这是因为补偿iler无法为Abstract[List,Int,String]
派生函子吗?
这是一个有点难以理解。编译器无法知道如何将'_'转换为'T',而不会被告知如何,对吗? – erip
基本上我想创建一个函数的包装,以这种方式,我可以映射到包装与其他函数来创建(组合)函数的新包装 – ixaxaar
这有帮助吗? – ixaxaar