2015-11-04 1 views
3

Higher kinded типов для Scala List, Функции и других сложных типов

Я все еще учусь Scala - Так что, пожалуйста, простите меня, если это очень просто сделать. Я также не очень свободно говорю с Scalaz или Shapeless - я только начинаю изучать эти библиотеки. Я ищу простой трактата, где-то что объясняет мне, как я могу сделать что-то вроде

trait AmazingMalini[F[G[_]]] { 
     def fMap[A,B](aa: F[G[A]])(f : A => F[G[B]]) : F[G[B]] 
} 

И тогда я хочу быть в состоянии сделать что-то вроде этого -

trait SomeCrazyMagicWithList extends AmazingMalini[Option[List]]{ 
    def fMap[A,B](aa: Option[List[A]])(f : A => Option[List[B]]) :Option[List[B]] = ??? 
} 

Заметьте, что опция или типы списка - это просто примеры. У меня есть несколько типов контейнеров, которые я бы заменил там (построив небольшой трафик, например DSL для приложения).

+0

Я не уверен, если это правильное решение, но, похоже, работает: 'trait AmazingMalini [F [G], G [_]]', 'trait SomeCrazyMagicWithList расширяет AmazingMalini [Option, List]'. Остальная часть кода не изменилась. –

+1

Я бы не использовал один и тот же идентификатор 'G' для разных вещей, это довольно запутанно. Другими словами, было бы лучше просто «AmazingMalini [F [_], G [_]]» –

ответ

5

Вы должны изменить подпись AmazingMalini к trait AmazingMalini[F[_], G[_]]

Метод может затем быть реализован следующим образом:

trait AmazingMalini[F[_], G[_]] { 
def fMap[A,B](aa: F[G[A]])(f : A => F[G[B]]) : F[G[B]] 
} 

trait SomeCrazyMagicWithList extends AmazingMalini[Option, List] { 
    def fMap[A, B](aa: Option[List[A]])(f: A => Option[List[B]]): Option[List[B]] = 
    aa.flatMap { 
     _ match { 
     case Nil   => Some(Nil) 
     case as: List[A] => as.map(f).reduce(concat(_, _)) 
     } 
    } 

    def concat[A](x: Option[List[A]], y: Option[List[A]]): Option[List[A]] = for { 
    xs <- x 
    ys <- y 
    } yield xs ++ ys 
} 

Обратите внимание, что Scalaz обеспечивает monad transformers чтобы обеспечить укладку некоторых монад , Например:

  • OptionT трансформатор обеспечивает укладку любой монады на вершине Option: List[Option[A]], Future[Option[A]] и т.д.
  • ListT трансформатор обеспечивает укладку любой монады на вершине List: Option[List[A]], Future[List[A]].

Таким образом, в вашем случае, вы могли бы использовать ListT так:

import scalaz._ 
import Scalaz._ 
import ListT._ 

listT(List(1,2,3).some).flatMap(i => listT(List(i, i * 3).some)) 

res0: scalaz.ListT[Option,Int] = ListT(Some(List(1, 3, 2, 6, 3, 9))) 

Вы также можете использовать для-постижений с монада трансформаторов:

for { 
    x <- listT(List(1,2).some) 
    y <- listT(List(3,4).some) 
} yield x + y 

res2: scalaz.ListT[Option,Int] = ListT(Some(List(4, 5, 5, 6))) 
+0

хороший ответ - я надеялся, что кто-то прокрадет лямбда-трюк - и, следовательно, объяснит мне синтаксис ... но это работает ;-) –

+0

@ user1525079 какой лямбда-трюк? : o – dcastro

+0

@ user1525079 Я думаю, вы имели в виду трюк типа «лямбда»: P [См. это сообщение для объяснения] (http://stackoverflow.com/questions/8736164/what-are-type-lambdas-in-scala- и-что-это-их выгода). – dcastro

Смежные вопросы