Eu tenho lido Haskell do mundo real e estou chegando ao fim, mas uma questão de estilo me incomoda com os operadores (.)
e ($)
.
Quando você escreve uma função que é uma composição de outras funções, você a escreve como:
f = g . h
Mas quando você aplica algo ao final dessas funções, escrevo-o assim:
k = a $ b $ c $ value
Mas o livro escreveria assim:
k = a . b . c $ value
Agora, para mim, eles parecem funcionalmente equivalentes, fazem exatamente a mesma coisa aos meus olhos. No entanto, quanto mais eu olho, mais vejo pessoas escrevendo suas funções da maneira que o livro faz: componha (.)
primeiro e depois apenas no final use ($)
para acrescentar um valor para avaliar o lote (ninguém o faz com muitas composições em dólares) .
Existe uma razão para usar a maneira livros muito melhor do que usar todos os ($)
símbolos? Ou existe alguma prática recomendada aqui que eu não estou conseguindo? Ou é supérfluo e eu não deveria me preocupar com isso?
fonte
k = a $ b $ c value
a . b $ c value
que não gosto tanto quanto no terceiro exemplo, mas salva alguns caracteres.Respostas:
Eu acho que posso responder isso por autoridade.
Não há motivo especial. Bryan e eu preferimos reduzir o ruído da linha.
.
é mais quieto que$
. Como resultado, o livro usa af . g . h $ x
sintaxe.fonte
f.g.h
como uma nova criação inteligentef(g(h()))
. Agora eles estão chamando uma nova função, embora anônima, que eles criaram, em vez de apenas encadear um grande dicionário de chamadas de função pré-fabricadas como um usuário PHP.Eles são de fato equivalentes: lembre-se de que o
$
operador não faz, essencialmente, nada.f $ x
avalia comof x
. O objetivo$
é o seu comportamento de fixação: associatividade correta e precedência mínima. Removendo$
e usando parênteses para agrupar em vez de precedência de infixo, os trechos de código têm a seguinte aparência:e
O motivo para preferir a
.
versão à$
versão é o mesmo motivo para preferir a versão entre parênteses acima: apelo estético.Embora alguns possam se perguntar se o uso de operadores infix em vez de parênteses se baseia em algum desejo subconsciente de evitar qualquer possível semelhança com o Lisp (brincadeira ... acho?).
fonte
Eu acrescentaria que
f . g $ x
,f . g
é uma unidade sintática significativa.Enquanto isso, em
f $ g $ x
,f $ g
não é uma unidade significativa. Uma cadeia de$
é sem dúvida mais imperativa - primeiro obtenha o resultadog
dex
, depois façaf
a ela, depois façafoo
a ela, então etc.Enquanto isso, uma cadeia
.
é sem dúvida mais declarativa e, em certo sentido, mais próxima de uma visão centrada no fluxo de dados - compõe uma série de funções e, em última análise, aplica-as a alguma coisa.fonte
$
operador parece se comportar de maneira semelhante ao<|
operador em F #. Acredito que ambos são definidos da mesma forma - em F #(<|) a b = a b
e em Haskella $ b = a b
, que são essencialmente equivalentes.(<|) b a = a b
em F #, já que é usado como[1; 2; 3; 4; 5] <| List.map ((+) 1)
se a memória servir.<|
operador passa o valor para a função, em vez de passar a função para o valor - seu exemplo de código funcionaria com o|>
operador.Para mim, acho que a resposta é (a) a limpeza, como Don disse ; e (b) acho que quando estou editando o código, minha função pode acabar no estilo sem pontos, e tudo o que preciso fazer é excluir o último em
$
vez de voltar e alterar tudo. Um ponto menor, certamente, mas um detalhe.fonte
Há uma discussão interessante sobre essa questão nesse tópico de haskell-café . Aparentemente há um ponto de vista minoria que sustenta que a associatividade direita
$
é "simplesmente errado plain" , e escolherf . g . h $ x
maisf $ g $ h $ x
é uma forma de contornando a questão.fonte
$!
também tem a associatividade certa "completamente errada" - por que o $! operador associativo certo? .É apenas uma questão de estilo. No entanto, a maneira como o livro faz isso faz mais sentido para mim. Compõe todas as funções e depois aplica-o ao valor.
Seu método parece estranho, e o último
$
é desnecessário.No entanto, isso realmente não importa. Em Haskell, geralmente existem muitas, muitas maneiras corretas de fazer a mesma coisa.
fonte
Sei que essa é uma pergunta muito antiga, mas acho que há outra razão para isso que não foi mencionada.
Se você estiver declarando uma nova função sem pontos
f . g . h
, o valor que você passar será aplicado automaticamente. No entanto, se você escreverf $ g $ h
, não funcionará.Eu acho que a razão pela qual o autor prefere o método de composição é porque leva a uma boa prática de criação de funções.
fonte