Estoy realmente interesado en descubrir dónde están las diferencias y, en general, identificar los casos de uso canónico en los que no se pueden usar las listas H (o mejor dicho, no producen ningún beneficio sobre las listas regulares).
(Soy consciente de que hay 22 (creo) TupleN
en Scala, mientras que uno solo necesita una sola HList, pero ese no es el tipo de diferencia conceptual que me interesa).
He marcado un par de preguntas en el texto a continuación. Puede que en realidad no sea necesario responderlas, están más destinadas a señalar cosas que no están claras para mí y a guiar la discusión en ciertas direcciones.
Motivación
Recientemente he visto un par de respuestas sobre SO en las que las personas sugirieron usar Listas H (por ejemplo, según lo proporcionado por Shapeless ), incluida una respuesta eliminada a esta pregunta . Dio lugar a esta discusión , que a su vez provocó esta pregunta.
Introducción
Me parece que las listas solo son útiles cuando se conoce el número de elementos y sus tipos precisos estáticamente. El número en realidad no es crucial, pero parece poco probable que alguna vez necesite generar una lista con elementos de tipos diferentes pero conocidos estadísticamente con precisión, pero que no sepa estáticamente su número. Pregunta 1: ¿Podría incluso escribir un ejemplo así, por ejemplo, en un bucle? Mi intuición es que tener una lista h estáticamente precisa con un número estáticamente desconocido de elementos arbitrarios (arbitrario en relación con una determinada jerarquía de clases) simplemente no es compatible.
HListas contra tuplas
Si esto es cierto, es decir, conoce estáticamente el número y el tipo. Pregunta 2: ¿por qué no usar una n-tupla? Claro, puede escribir de forma segura en un mapa y plegar sobre una HList (que también puede, pero no escribir de forma segura, sobre una tupla con la ayuda de productIterator
), pero dado que el número y el tipo de elementos son estáticos, probablemente pueda acceder a los elementos de la tupla. directamente y realizar las operaciones.
Por otro lado, si la función f
que mapea en una hlist es tan genérica que acepta todos los elementos - Pregunta 3: ¿por qué no usarla productIterator.map
? Ok, una diferencia interesante podría venir de la sobrecarga de métodos: si tuviéramos varias sobrecargadas f
, tener la información de tipo más fuerte proporcionada por hlist (en contraste con el ProductIterator) podría permitirle al compilador elegir una más específica f
. Sin embargo, no estoy seguro de si eso realmente funcionaría en Scala, ya que los métodos y las funciones no son lo mismo.
Listas y entrada del usuario
Partiendo de la misma suposición, a saber, que necesita saber el número y los tipos de los elementos de forma estática. Pregunta 4: ¿ se pueden utilizar las listas en situaciones en las que los elementos dependen de cualquier tipo de interacción del usuario? Por ejemplo, imagine llenar una lista con elementos dentro de un bucle; los elementos se leen desde algún lugar (UI, archivo de configuración, interacción del actor, red) hasta que se cumpla una determinada condición. ¿Cuál sería el tipo de hlist? Similar para una especificación de interfaz getElements: HList [...] que debería funcionar con listas de longitud estáticamente desconocida, y que permite que el componente A en un sistema obtenga dicha lista de elementos arbitrarios del componente B.
FunctionN
rasgos no saben cómo abstraer sobre arity : github.com/paulbutcher/ScalaMock/blob/develop/core/src/main/… github.com/paulbutcher/ScalaMock/blob / desarrollo / core / src / main / ... Lamentablemente no estoy al tanto de cualquier manera que pueda utilizar sin forma de evitar esto, dado que necesito para hacer frente a "real"FunctionN
sPara ser claros, una HList no es más que una pila de
Tuple2
azúcar ligeramente diferente en la parte superior.Entonces, su pregunta es esencialmente sobre las diferencias entre el uso de tuplas anidadas frente a las tuplas planas, pero las dos son isomorfas, por lo que al final realmente no hay diferencia, excepto la conveniencia de qué funciones de biblioteca se pueden usar y qué notación se puede usar.
fuente
Hay muchas cosas que no puedes hacer (bueno) con las tuplas:
Puedes hacer todo eso con tuplas, por supuesto, pero no en el caso general. Entonces, usar HLists hace que su código sea más SECO.
fuente
Puedo explicar esto en un lenguaje súper simple:
La nomenclatura tupla vs lista no es significativa. Las listas H se pueden nombrar como HTuples. La diferencia es que en Scala + Haskell, puedes hacer esto con una tupla (usando la sintaxis de Scala):
para tomar una tupla de entrada de exactamente dos elementos de cualquier tipo, agregar un tercer elemento y devolver una tupla completamente tipada con exactamente tres elementos. Pero si bien esto es completamente genérico sobre los tipos, tiene que especificar explícitamente las longitudes de entrada / salida.
Lo que una lista HList de estilo Haskell le permite hacer es hacer que este genérico se extienda a lo largo, para que pueda agregar cualquier longitud de tupla / lista y recuperar una tupla / lista totalmente estáticamente escrita. Este beneficio también se aplica a las colecciones de tipo homogéneo donde puede agregar un int a una lista de exactamente n ints y recuperar una lista que está estáticamente tipada para tener exactamente (n + 1) ints sin especificar explícitamente n.
fuente