Qual é a maneira mais curta de expressar a função
f(a,b)(c,d)=(a+c,b+d)
em notação sem ponto?
pointfree.io nos dá
uncurry (flip flip snd . (ap .) . flip flip fst . ((.) .) . (. (+)) . flip . (((.) . (,)) .) . (+))
que com um pouco de trabalho pode ser reduzido para
uncurry$(`flip`snd).((<*>).).(`flip`fst).((.).).(.(+)).flip.(((.).(,)).).(+)
por 76 bytes. Mas isso ainda parece muito longo e complexo para uma tarefa tão simples. Existe alguma maneira de expressar a adição aos pares como uma função sem pontos mais curta?
Para ficar claro com o que quero dizer com sem ponto, uma declaração sem ponto de uma função envolve pegar funções e operadores existentes e aplicá-los um ao outro de modo que a função desejada seja criada. Acentos graves, parênteses e valores literais ( []
, 0
, [1..3]
, etc) são permitidos, mas palavras-chave como where
e let
não são. Isso significa:
Você não pode atribuir nenhuma variável / função
Você não pode usar lambdas
Você não pode importar
(+)***(+)
.(+)<$>([1],2)<*>([3],4)
dá([1,3],6)
.Respostas:
44 bytes
Obtive isso de
\x y -> (fst x + fst y, snd x + snd y)
Experimente online!
fonte
44 bytes
-8 bytes graças a Ørjan Johansen. -3 bytes graças a Bruce Forte.
Experimente online!
Traduz para:
67 bytes
-8 bytes graças a Ørjan Johansen. -1 byte graças a Bruce Forte.
Se a saída da tupla for necessária:
Experimente online!
Sim, eu manualmente não produz frutos maduros. Mas estou feliz com a
[a] → (a, a)
conversão.Agora, se houvesse uma função curta com
m (a → b) → a → m b
.fonte
mapM id[fst,snd]
é mais curto.mapM id
é a versão em golf da função que você provavelmente está procurandosequence
,.(<*>)
a assinatura que ém (a → b) → m a → m b
. Tão perto ...Control.Lens.??
, o que pode ter sido proposto para inclusão na base em algum momento.(.mapM id[fst,snd])
comolet r=(.mapM id[fst,snd]) in r(r.zipWith(+))
, mas eu não tenho sido capaz de obter o typechecker a aceitar uma versão pointfree.54 bytes
Sinceramente, duvido que venceremos a solução de 44 bytes do @PWiz, mas ninguém estava usando o fato de
(,)
implementar a classe typeFunctor
, então aqui está outra interessante que não é tão ruim:Experimente online!
Explicação
A implementação da classe type
Functor
para 2 -Tuples é muito semelhante à deEither
(da base-4.10.1.0 ):O que isso significa para esse desafio é que a função a seguir adiciona os segundos elementos enquanto mantém o primeiro elemento do segundo argumento:
Então, se tivéssemos algum ajudante
helpPlz = \a b -> (fst a+fst b,snd b)
, poderíamos fazer(helpPlz<*>).flip(fmap.(+).snd)
e estaríamos prontos. Felizmente, temos a ferramentapointfree
que nos dá:Então, simplesmente reconectando essa função, chegamos à solução acima (observe a
(<*>) = ap
que está na base ).fonte
60 bytes
Não estou vendo nenhum
uncurry
amor aqui, então imaginei que iria aparecer e consertar isso.Eu pensei, com todos os
fst
esnd
, que descompactar os argumentos comuncurry
poderia produzir alguns resultados. Claramente, não foi tão proveitoso quanto eu esperava.fonte
uncurry
é tão detalhado. :( Mas você pode substituir os parênteses mais externos por$
.