У меня есть и 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) }
}
Я хочу отобразить их, поэтому я определил Functor следующим образом:
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) } })
}
}
}
Теперь, чтобы на самом деле сопоставить Abstract, мне понадобится 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 }
}
or
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>)
}
Однако в этом шаблоне мне пришлось бы определять объекты case для всех возможных E
. Вот мои вопросы:
- Это правильный способ использования функторов?
- Как я могу автоматизировать создание объектов case для всех возможных
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]
Я предполагаю, что это потому, что компилятор не может получить функтор для Abstract[List,Int,String]
?
_
вT
, не зная, как это сделать, верно? - person erip   schedule 19.06.2017