Es gibt ein paar Probleme hier. Der erste ist, dass der statische Typ Ihrer hlist Some
darin statt Option
hat, so dass die Beweise, dass Sie beweisen müssen, dass uuu
über options
zugeordnet werden kann nicht gefunden werden. Der schönste Weg, dies zu beheben, ist ein intelligentes Some
Konstruktor zu definieren, liefert ein Option
:
def some[A](a: A): Option[A] = Some(a)
val options = some(1) :: some("A") :: some(3.5) :: HNil
Sie könnten auch Typenannotationen zu Ihren ursprünglichen options
hinzufügen oder uuu
mit Some
statt Option
(die würde arbeiten ändern sein sicherer, aber vermutlich weniger nützlich für alles, was Sie erreichen wollen.
Jetzt kompiliert Ihr Code und tut etwas, aber nur wegen der etwas bizarren Tatsache, dass Any
in Scala freundlich-polymorph ist. Wenn Sie F ~> G
haben, müssen sowohl F
als auch G
Typkonstruktoren sein, die einen einzigen Typparameter verwenden, z. Option ~> List
. Any
nimmt keinen Typparameter, und doch funktioniert es, wegen dieser merkwürdigen Tatsache über die Scala-Sprache (die Any
, zusammen mit Nothing
, ist irgendwie polymorph und wird jeden Platz passen, wo Sie einen Typ benötigen, einen Typkonstruktor mit ein Parameter, ein Typkonstruktor mit einem Dutzend Parametern usw.).
So kompiliert es, aber es ist ziemlich nutzlos, da es eine Any :: Any :: Any :: HNil
zurückgibt. Sie können dieses Problem beheben, indem Sie die Any
in der natürlichen Transformation mit shapeless.Id
ersetzt:
import shapeless._, shapeless.poly.~>
def some[A](a: A): Option[A] = Some(a)
val options = some(1) :: some("A") :: some(3.5) :: HNil
object uuu extends (Option ~> Id) {
def apply[T](l: Option[T]): T = l.get
}
options.map(uuu)
Id
ist definiert als type Id[+T] = T
-i.e., es ist die Identität Typkonstruktor, dass Sie die ungeöffneten Art gibt.
Diese Version beide compiliert und gibt Ihnen wieder ein nutzbringend typisierte Ergebnis, aber es ist immer noch nicht wirklich sicher, da, wenn Sie eine Karte über hlist
mit Elementen, die None
(zur Laufzeit) sind, können Sie eine NoSuchElementException
bekommen. Es gibt nicht wirklich einen Weg um dies zu ändern, abgesehen von der Änderung Option ~> Id
zu Some ~> Id
, irgendwie Bereitstellung von Standardwerten, etc., die alle die Art der Operation ziemlich dramatisch ändern.
Könntest du bitte erklären: "Irgendwelche sind in Scala irgendwie polymorph", Travis? –
@KevinMeredith Nun, dieser Abschnitt erklärt die Grundlagen.Um etwas Konkreteres zu definieren, definiere 'def foo [F [_, _, _]] (f: F [Int, Int, Int]) = f' und versuche 'foo [Any] (1)'. –