Eu gosto de pensar em Arrows, como Mônadas e Functors, como permitindo que o programador faça composições exóticas de funções.
Sem Mônadas ou Setas (e Functors), a composição de funções em uma linguagem funcional é limitada à aplicação de uma função ao resultado de outra função. Com mônadas e functores, você pode definir duas funções e, em seguida, escrever código reutilizável separado, que especifica como essas funções, no contexto de determinada mônada, interagem entre si e com os dados que são passados para elas. Este código é colocado dentro do código de ligação da Mônada. Portanto, uma mônada é uma visualização única, apenas um contêiner para código de ligação reutilizável. As funções são compostas de maneira diferente no contexto de uma mônada de outra mônada.
Um exemplo simples é a mônada Maybe, onde há código na função de ligação, de modo que, se uma função A é composta por uma função B dentro de uma mônada Maybe e B produz um Nothing, o código de ligação garantirá que a composição da duas funções produzem a Nothing, sem se preocupar em aplicar A ao valor Nothing saindo de B. Se não houvesse mônada, o programador teria que escrever código em A para testar a entrada Nothing.
Mônadas também significam que o programador não precisa digitar explicitamente os parâmetros exigidos por cada função no código-fonte - a função bind lida com a passagem de parâmetros. Portanto, usando mônadas, o código fonte pode começar a parecer mais uma cadeia estática de nomes de funções, em vez de parecer que a função A "chama" a função B com os parâmetros C e D - o código começa a parecer mais um circuito eletrônico do que um máquina em movimento - mais funcional que imperativa.
As setas também conectam funções com uma função de ligação, fornecendo funcionalidade reutilizável e ocultando parâmetros. Porém, as próprias setas podem ser conectadas e compostas e, opcionalmente, podem rotear dados para outras setas em tempo de execução. Agora você pode aplicar dados a dois caminhos de Arrows, que "fazem coisas diferentes" aos dados e remontam o resultado. Ou você pode selecionar para qual ramificação das setas passar os dados, dependendo de algum valor nos dados. O código resultante é ainda mais parecido com um circuito eletrônico, com comutadores, atrasos, integração etc. O programa parece muito estático e você não deve conseguir ver muita manipulação de dados acontecendo. Há cada vez menos parâmetros para se pensar e menos necessidade de pensar sobre quais valores os parâmetros podem ou não levar.
Escrever um programa Arrowized envolve principalmente selecionar Setas prontas como divisores, comutadores, atrasos e integradores, elevar funções nessas Setas e conectar as Setas para formar Setas maiores. Na Programação Reativa Funcional Arrowizada, as Setas formam um loop, com a entrada do mundo combinada com a saída da última iteração do programa, para que a saída reaja à entrada do mundo real.
Um dos valores do mundo real é o tempo. No Yampa, a Seta de Função de Sinal encobre invisivelmente o parâmetro time através do programa de computador - você nunca acessa o valor do tempo, mas se conectar uma seta integradora ao programa, ela produzirá valores integrados ao longo do tempo que você poderá usar para passar para outras flechas.