scala - trabajo - problemas que presentan las bibliotecas
¿Puede alguien explicarme para qué sirve la biblioteca Shapeless? (3)
¿Puede alguien explicarme en términos simples para qué sirve la biblioteca Shapeless?
Scala tiene genéricos y funcionalidad de herencia, así que estoy un poco confundido por lo que Shapeless es.
Tal vez un caso de uso para aclarar las cosas sería útil.
Es un poco difícil de explicar, ya que sin forma tiene una amplia gama de características; Probablemente me resulte más fácil "explicar, en términos simples, para qué son las variables". Definitivamente desea comenzar con la descripción general de la función .
En términos generales, sin forma se trata de programar con tipos. Hacer cosas en tiempo de compilación que normalmente se realizarían en tiempo de ejecución, manteniendo un seguimiento preciso del tipo de cada elemento en una lista, pudiendo traducir de tuplas a HLists a clases de casos, creando funciones polimórficas (a diferencia de los métodos), etc.
Un escenario de uso típico sería algo así como:
- Lea un montón de valores de algún lugar en una
List
- realizar un molde seguro de tipo de esa
List
en unaHList
- mapa sobre esa lista
HList
con una función polimórfica que, por ejemplo, normaliza los valores - Convierta el tercer elemento (que se sabe estáticamente que es un
Int
) en una cadena de 0 rellenos - construir una clase de caso usando valores de HList
Como referencia, una HList
tendrá un tipo preciso, como Int :: String :: Boolean :: HNil
(sí, que realmente es un solo tipo) donde todo está anclado y el tamaño es fijo. Por lo tanto, o necesita saber en el momento de la compilación exactamente lo que ingresará en su HList, o si necesita un modelo seguro.
Si tomas la tail
de una lista HList, obtienes una String :: Boolean :: HNil
y una garantía en tiempo de compilación de que el jefe de esto será una String
. El anteponer un valor al encabezado conservará de manera similar todos los tipos implicados.
Shapeless también viene con la clase de tipo Generic
, lo que le permite usar operaciones HList en tuplas y clases de casos también.
Las otras características que tiendo a usar son:
Coproducts
, que le permiten escribir estáticamente un valor como, por ejemplo, "unString
,Double
oInt
, pero nada más" (muy parecido aEither
, pero no limitado a solo dos posibilidades)Lenses
, que simplifican el trabajo con clases de casos anidados.
Todo en Shapeless tiene dos cosas en común:
Primero, no está en la biblioteca estándar de Scala, pero podría decirse que debería estarlo. Por lo tanto, preguntarse para qué sirve Shapeless es un poco como preguntar con la biblioteca estándar de Scala. Es para todo . Es una bolsa de sorpresas.
(Pero no es una bolsa de sorpresas totalmente arbitraria, porque :)
En segundo lugar, todo en Shapeless proporciona mayor control y seguridad en tiempo de compilación . Nada en Shapeless (¿en qué puedo pensar?) Realmente "hace" algo en tiempo de ejecución. Toda la acción interesante ocurre cuando se compila tu código. El objetivo siempre es aumentar la confianza de que si el código compila en absoluto, no se bloqueará o hará lo incorrecto en el tiempo de ejecución. (De ahí esta notable ocurrencia: https://twitter.com/mergeconflict/status/304090286659866624 )
Hay una buena introducción a lo que se trata la programación a nivel de tipo, con enlaces a recursos adicionales, en https://.com/a/4443972/86485 .
Ver una HList
es algo que puede parecer desconcertante hasta que intente trabajar con tipos y delegar o activar tipos. Eche un vistazo a lo siguiente:
val myList = 1 :: 2 :: "3" :: fred :: Nil
¿Cuál es el tipo de myList
aquí? Si tuviera que inspeccionarlo, vería que era de tipo List[Any]
. Eso no es muy útil. Lo que es aún menos útil es si traté de usar la siguiente función PartialFunction[Any]
para map
sobre ella:
myList.map{
case x: Int => x
case x: String => Int.parseInt(x)
}
En tiempo de ejecución, esto podría arrojar un MatchError
porque en realidad no te he dicho qué tipo es fred
. Podría ser de tipo Fred
.
Con una HList
puede saber en tiempo de compilación si no ha capturado uno de los tipos de esa lista. En lo anterior, si hubiera definido myList = 1 :: 2 :: "3" :: fred :: HNil
cuando myList = 1 :: 2 :: "3" :: fred :: HNil
al tercer elemento, su tipo sería String
y esto se conocería en tiempo de compilación.
Como dice @KevinWright, hay algo más que eso con Shapeless, pero HList
es una de las características definitorias de la biblioteca.