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?

Foi útil?

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)]}))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top