Estou realmente interessado em descobrir onde estão as diferenças e, de maneira mais geral, identificar casos de uso canônicos em que as HLists não podem ser usadas (ou melhor, não produzem nenhum benefício em relação às listas regulares).
(Estou ciente de que existem 22 (acredito)) TupleN
em Scala, enquanto um só precisa de uma única HList, mas esse não é o tipo de diferença conceitual em que estou interessado.)
Marquei algumas perguntas no texto abaixo. Talvez não seja realmente necessário respondê-las, elas têm mais a intenção de apontar coisas que não são claras para mim e orientar a discussão em determinadas direções.
Motivação
Recentemente, vi algumas respostas no SO, nas quais as pessoas sugeriram o uso de HLists (por exemplo, conforme fornecido por Shapeless ), incluindo uma resposta excluída para esta pergunta . Isso deu origem a essa discussão , que por sua vez provocou essa questão.
Introdução
Parece-me que hlists são úteis apenas quando você conhece estaticamente o número de elementos e seus tipos precisos. O número não é realmente crucial, mas parece improvável que você precise gerar uma lista com elementos de tipos variados, mas estaticamente precisamente conhecidos, mas que não saiba estaticamente o número deles. Pergunta 1: Você poderia escrever um exemplo como, por exemplo, em um loop? Minha intuição é que ter uma lista estaticamente precisa com um número estaticamente desconhecido de elementos arbitrários (arbitrário em relação a uma determinada hierarquia de classes) simplesmente não é compatível.
HLists vs. Tuplas
Se isso for verdade, ou seja, você sabe estaticamente o número e o tipo - Pergunta 2: por que não usar apenas uma n-tupla? Claro, você pode tipicamente mapear e dobrar uma HList (que você também pode, mas não tipicamente, fazer sobre uma tupla com a ajuda de productIterator
), mas como o número e o tipo dos elementos são estaticamente conhecidos, você provavelmente pode acessar os elementos da tupla diretamente e executar as operações.
Por outro lado, se a função que f
você mapeia sobre uma lista é tão genérica que aceita todos os elementos - Pergunta 3: por que não usá-la productIterator.map
? Ok, uma diferença interessante poderia vir da sobrecarga de método: se tivéssemos várias sobrecarregadas f
, ter as informações de tipo mais fortes fornecidas pela hlist (em contraste com o productIterator) poderia permitir ao compilador escolher uma mais específica f
. No entanto, não tenho certeza se isso realmente funcionaria no Scala, pois métodos e funções não são os mesmos.
HLists e entrada do usuário
Com base na mesma suposição, a saber, que você precisa conhecer o número e os tipos dos elementos estaticamente - Questão 4: as listas podem ser usadas em situações em que os elementos dependem de qualquer tipo de interação do usuário? Por exemplo, imagine preencher uma hlist com elementos dentro de um loop; os elementos são lidos de algum lugar (interface do usuário, arquivo de configuração, interação do ator, rede) até que uma determinada condição seja mantida. Qual seria o tipo da lista? Semelhante para uma especificação de interface getElements: [...] HList que deve funcionar com listas de tamanho estaticamente desconhecido e que permite que o componente A em um sistema obtenha essa lista de elementos arbitrários do componente B.
FunctionN
características não sabem abstrair a aridade: github.com/paulbutcher/ScalaMock/blob/develop/core/src/main/… github.com/paulbutcher/ScalaMock/blob / desenvolver / core / src / main / ... Infelizmente eu não estou ciente de qualquer maneira que eu possa usar Shapeless para evitar isso, já que eu preciso para lidar com "real"FunctionN
sSó para esclarecer, uma HList nada mais é do que uma pilha de
Tuple2
açúcar ligeiramente diferente por cima.Portanto, sua pergunta é essencialmente sobre as diferenças entre o uso de tuplas aninhadas e de tuplas planas, mas as duas são isomórficas; portanto, no final, realmente não há diferença, exceto a conveniência de que funções da biblioteca podem ser usadas e qual notação pode ser usada.
fonte
Há muitas coisas que você não pode fazer (bem) com tuplas:
Você pode fazer tudo isso com tuplas, é claro, mas não no caso geral. Portanto, usar HLists torna seu código mais SECO.
fonte
Eu posso explicar isso em linguagem super simples:
A nomeação de tupla versus lista não é significativa. HLists podem ser nomeadas como HTuples. A diferença é que, no Scala + Haskell, você pode fazer isso com uma tupla (usando a sintaxe do Scala):
para obter uma tupla de entrada com exatamente dois elementos de qualquer tipo, anexar um terceiro elemento e retornar uma tupla totalmente digitada com exatamente três elementos. Mas, embora seja genérico sobre os tipos, ele precisa especificar explicitamente os comprimentos de entrada / saída.
O que um HList do estilo Haskell permite fazer é tornar esse genérico excedente, para que você possa anexar a qualquer comprimento da tupla / lista e recuperar uma lista / tupla totalmente digitada estaticamente. Esse benefício também se aplica a coleções de tipo homogêneo, nas quais você pode anexar um int a uma lista de exatamente n ints e recuperar uma lista que é digitada estaticamente para ter exatamente (n + 1) ints sem especificar explicitamente n.
fonte