MATERALIZAÇÃO DE PADRÃO VALORES idênticos
-
19-09-2019 - |
Pergunta
Eu me perguntei se é possível corresponder aos mesmos valores por várias vezes com as instalações de correspondência de padrões de linguagens de programação funcionais (Haskell/F#/CAML).
Basta pensar no exemplo a seguir:
plus a a = 2 * a
plus a b = a + b
A primeira variante seria chamada quando a função for invocada com dois valores semelhantes (que seriam armazenados em a
).
Um aplicativo mais útil seria esse (simplificando um AST).
simplify (Add a a) = Mult 2 a
Mas Haskell rejeita esses códigos e me avisa de definições conflitantes para a
- Eu tenho que fazer um caso explícito/se verifica para descobrir se a função obteve valores idênticos. Existe algum truque para indicar que uma variável que eu quero combinar ocorrerá várias vezes?
Solução
Isso é chamado de padrão não linear. Houve vários tópicos na lista de discussão Haskell-Cafe sobre isso, há pouco tempo. Aqui estão dois:
http://www.mail-archive.com/haskell-cafe@haskell.org/msg59617.html
http://www.mail-archive.com/haskell-cafe@haskell.org/msg62491.html
Conclusão: não é impossível implementar, mas foi decidido contra a simplicidade.
A propósito, você não precisa if
ou case
para contornar isso; A maneira (um pouco mais limpa é usar um guarda:
a `plus` b
| a == b = 2*a
| otherwise = a+b
Outras dicas
Você não pode ter dois parâmetros com o mesmo nome para indicar que eles devem ser iguais, mas você pode usar guardas Para distinguir casos como este:
plus a b
| a == b = 2 * a
| otherwise = a + b
Isso é mais flexível, pois também funciona para condições mais complicadas do que a igualdade simples.
Acabei de procurar os tópicos da lista de discussão fornecidos na resposta de Thomas, e a primeira resposta em um deles faz sentido e explica por que esse "padrão" não faria muito sentido em geral: e se a
é uma função? (É impossível em geral verificar se as funções são iguais.)
Haskell não faz unificação.
Eu implementei uma nova linguagem de programação funcional que pode lidar com padrões não lineares em Haskell.
https://github.com/egison/egison
No meu idioma, seu plus
função escrita da seguinte forma.
(define $plus
(match-lambda [integer integer]
{[[$a ,a] (* a 2)]
[[$a $b] (+ a b)]}))