Di solito non è possibile descrivere vincoli interessanti come questo utilizzando un tipo alias invece si vuole una classe tipo che servirà come prova che una il tipo ha qualche proprietà.
Con Shapeless è spesso possibile eseguire questo utilizzando le classi di tipi fornite dalla libreria, ma non penso che sia il caso qui. Per fortuna non è troppo difficile da scrivere il proprio:
import shapeless._
// Evidence that an hlist is made up of functions that can be composed.
trait Composable[L <: HList] {
type In
}
object Composable {
type Aux[L <: HList, In0] = Composable[L] { type In = In0 }
implicit def composable0[A, B]: Aux[(A => B) :: HNil, A] =
new Composable[(A => B) :: HNil] {
type In = A
}
implicit def composable1[A, B, T <: HList]
(implicit tc: Aux[T, B]): Aux[(A => B) :: T, A] =
new Composable[(A => B) :: T] {
type In = A
}
}
def composable[L <: HList: Composable] {}
Quello che stiamo facendo qui sta descrivendo come costruire prove induttivo, con Singleton HList
come il caso base. Ad ogni passaggio utilizziamo il membro del tipo In
per tenere traccia di ciò che deve essere il tipo di output della funzione successiva (vale a dire prima nella lista).
E per confermare che fa quello che ci aspettiamo:
scala> composable[(Int => String) :: (String => Char) :: HNil]
scala> composable[(Int => Long) :: (Long => Char) :: (Char => String) :: HNil]
scala> composable[(Int => String) :: (Symbol => Char) :: HNil]
<console>:23: error: could not find implicit value for evidence parameter...
I primi due funzionano bene, mentre il terzo non viene compilato.
fonte
2015-03-03 21:14:06
Risposta che funziona ed è educativo. Grazie! È interessante notare come il vostro esempio funzioni anche quando sostituisco i corpi di 'composable0' e' componable1' con 'null'. Tuttavia, avrò bisogno dell'istanza typeclass quando cerco di fare effettivamente qualcosa con la lista che sfrutta la componibilità, che dovrò fare attraverso i metodi typeclass, suppongo. –
Questo è giusto in questo caso probabilmente dovrai anche aggiungere un membro di tipo 'Out' per fare qualcosa di utile oltre a fornire prove che i tipi si allineino. –