Pergunta

No meu segundo ano de universidade nos "ensinaram" Haskell, não sei quase nada sobre isso e menos ainda sobre programação funcional.

O que é programação funcional, por que e/ou onde eu gostaria de usá-la em vez de programação não funcional e estou correto ao pensar que C é uma linguagem de programação não funcional?

Foi útil?

Solução

Uma característica fundamental em uma linguagem funcional é o conceito de funções de primeira classe.A ideia é que você possa passar funções como parâmetros para outras funções e retorná-las como valores.

A programação funcional envolve escrever código que não muda de estado.A principal razão para fazer isso é que chamadas sucessivas a uma função produzirão o mesmo resultado.Você pode escrever código funcional em qualquer linguagem que suporte funções de primeira classe, mas existem algumas linguagens, como Haskell, que não permitem alterar o estado.Na verdade, você não deve causar nenhum efeito colateral (como imprimir texto) - o que parece ser completamente inútil.

Em vez disso, Haskell emprega uma abordagem diferente para IO:mônadas.Estes são objetos que contêm a operação IO desejada a ser executada pelo nível superior do seu intérprete.Em qualquer outro nível são simplesmente objetos no sistema.

Que vantagens a programação funcional oferece?A programação funcional permite codificação com menos potencial para bugs porque cada componente é completamente isolado.Além disso, o uso de recursão e funções de primeira classe permite provas simples de correção que normalmente refletem a estrutura do código.

Outras dicas

O que é programação funcional

Existem duas definições diferentes de "programação funcional" de uso comum hoje:

A definição mais antiga (originária do Lisp) é que programação funcional trata de programar usando funções de primeira classe, ou seja,onde as funções são tratadas como qualquer outro valor para que você possa passar funções como argumentos para outras funções e a função pode retornar funções entre seus valores de retorno.Isso culmina no uso de funções de ordem superior, como map e reduce (você já deve ter ouvido falar mapReduce como uma operação única muito utilizada pelo Google e, sem surpresa, é um parente próximo!).Os tipos .NET System.Func e System.Action disponibilizar funções de ordem superior em C#.Embora currying seja impraticável em C#, funções que aceitam outras funções como argumentos são comuns, por exemplo.o Parallel.For função.

A definição mais recente (popularizada por Haskell) é que a programação funcional também trata de minimizar e controlar os efeitos colaterais, incluindo mutação, ou seja,escrever programas que resolvem problemas compondo expressões.Isso é mais comumente chamado de "programação puramente funcional".Isso é possível graças a abordagens totalmente diferentes de estruturas de dados, chamadas de "estruturas de dados puramente funcionais".Um problema é que traduzir algoritmos imperativos tradicionais para usar estruturas de dados puramente funcionais normalmente piora o desempenho em 10 vezes.Haskell é a única linguagem de programação puramente funcional sobrevivente, mas os conceitos se infiltraram na programação convencional com bibliotecas como Linq na rede.

onde eu gostaria de usá-lo em vez de programação não funcional

Em todos os lugares.Lambdas em C# já demonstraram grandes benefícios.C++ 11 possui lambdas.Não há desculpa para não usar funções de ordem superior agora.Se você puder usar uma linguagem como F#, você também se beneficiará da inferência de tipo, generalização automática, curry e aplicação parcial (além de muitos outros recursos da linguagem!).

estou correto ao pensar que C é uma linguagem de programação não funcional?

Sim.C é uma linguagem processual.No entanto, você pode obter alguns benefícios da programação funcional usando ponteiros de função e void * em C.

Pode valer a pena conferir este artigo sobre F# "101" no CoDe Mag postado recentemente.

Também, Dustin Campbell tem um ótimo blog onde ele postou muitos artigos sobre suas aventuras para se familiarizar com o F#.

Espero que você ache isso útil :)

EDITAR:

Além disso, só para acrescentar, meu entendimento de programação funcional é que tudo é uma função ou parâmetros para uma função, em vez de instâncias/objetos com estado.Mas posso estar errado. F# é algo que estou morrendo de vontade de fazer, mas simplesmente não tenho tempo!:)

O código de exemplo de John, o Estatístico, não mostra programação funcional, porque quando você está fazendo programação funcional, a chave é que o código NÃO faça ATRIBUIÇÕES ( record = thingConstructor(t) é uma tarefa) e NÃO TEM EFEITOS COLATERAIS (localMap.put(record) é uma afirmação com efeito colateral).Como resultado destas duas restrições, tudo o que um função does é totalmente capturado por seus argumentos e seu valor de retorno.Reescrevendo o código do Estatístico da maneira que deveria ser, se você quisesse emular uma linguagem funcional usando C++:

RT getOrCreate(const T thing, 
                  const Function<RT<T>> thingConstructor, 
                  const Map<T,RT<T>> localMap) {
    return localMap.contains(t) ?
        localMap.get(t) :
        localMap.put(t,thingConstructor(t));
}

Como resultado da regra de não haver efeitos colaterais, cada instrução faz parte do valor de retorno (portanto return vem primeiro) e cada instrução é uma expressão.Em linguagens que impõem programação funcional, o return a palavra-chave está implícita e o se instrução se comporta como C++ ?: operador.

Além disso, tudo é imutável, então localMap.put tem que criar uma nova cópia de mapa local e devolvê-lo, em vez de modificar o original mapa local, da mesma forma que um programa C++ ou Java normal faria.Dependendo da estrutura do localMap, a cópia pode reutilizar ponteiros no original, reduzindo a quantidade de dados que devem ser copiados.

Algumas das vantagens da programação funcional incluem o fato de que os programas funcionais são mais curtos e é mais fácil modificar um programa funcional (porque não há efeitos globais ocultos a serem considerados) e é mais fácil acertar o programa no primeiro lugar.

No entanto, os programas funcionais tendem a ser executados lentamente (por causa de todas as cópias que precisam fazer) e não tendem a interagir bem com outros programas, processos do sistema operacional ou sistemas operacionais que lidam com endereços de memória, little-endian blocos de bytes e outros bits não funcionais específicos da máquina.O grau de não interoperabilidade tende a ser inversamente correlacionado com o grau de pureza funcional e com o rigor do sistema de tipos.

As linguagens funcionais mais populares têm sistemas de tipos muito, muito rígidos.No OCAML, você não pode nem misturar números inteiros e números de ponto flutuante, ou usar os mesmos operadores (+ é para adicionar números inteiros, +.é para adicionar carros alegóricos).Isso pode ser uma vantagem ou uma desvantagem, dependendo de quanto você valoriza a capacidade de um verificador de tipo de detectar certos tipos de bugs.

Linguagens funcionais também tendem a ter ambientes de execução realmente grandes.Haskell é uma exceção (os executáveis ​​GHC são quase tão pequenos quanto os programas C, tanto em tempo de compilação quanto em tempo de execução), mas os programas SML, Common Lisp e Scheme sempre exigem toneladas de memória.

Sim, você está correto ao pensar que C é uma linguagem não funcional.C é uma linguagem processual.

Prefiro usar programação funcional para evitar trabalhos repetidos, criando uma versão mais abstrata e depois usando-a.Deixe-me dar um exemplo.Em Java, muitas vezes me pego criando mapas para registrar estruturas e, assim, escrevendo estruturas getOrCreate.

SomeKindOfRecord<T> getOrCreate(T thing) { 
    if(localMap.contains(t)) { return localMap.get(t); }
    SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(t);
    localMap = localMap.put(t,record);
    return record; 
}

Isso acontece com muita frequência.Agora, em uma linguagem funcional eu poderia escrever

RT<T> getOrCreate(T thing, 
                  Function<RT<T>> thingConstructor, 
                  Map<T,RT<T>> localMap) {
    if(localMap.contains(t)) { return localMap.get(t); }
    RT<T> record = thingConstructor(t);
    localMap = localMap.put(t,record);
    return record; 
}

e eu nunca mais teria que escrever um novo desses, eu poderia herdá-lo.Mas eu poderia fazer melhor do que herdar, eu poderia dizer no construtor dessa coisa

getOrCreate = myLib.getOrCreate(*,
                                SomeKindOfRecord<T>.constructor(<T>), 
                                localMap);

(onde * é uma espécie de notação "deixe este parâmetro aberto", que é uma espécie de currying)

e então o getOrCreate local é exatamente o mesmo que teria sido se eu escrevesse tudo, em uma linha, sem dependências de herança.

Se você está procurando um bom texto em F#

Especialista F# é co-escrito por Don Syme.Criador do F#.Ele trabalhou em genéricos em .NET especificamente para poder criar F#.

F# é modelado a partir do OCaml, portanto, qualquer texto do OCaml também ajudaria você a aprender F#.

eu acho O que é programação funcional? Ser útil

A programação funcional é sobre escrever funções puras, sobre a remoção de entradas e saídas ocultas o máximo possível, para que o máximo possível de nosso código descreva apenas uma relação entre entradas e saídas.

Prefira explícito when parâmetro

public Program getProgramAt(TVGuide guide, int channel, Date when) {
  Schedule schedule = guide.getSchedule(channel);

  Program program = schedule.programAt(when);

  return program;
}

sobre

public Program getCurrentProgram(TVGuide guide, int channel) {
  Schedule schedule = guide.getSchedule(channel);

  Program current = schedule.programAt(new Date());

  return current;
}

Uma linguagem funcional é ativamente hostil aos efeitos colaterais.Os efeitos colaterais são complexidade e complexidade são bugs e bugs são o diabo.Uma linguagem funcional também o ajudará a ser hostil aos efeitos colaterais.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top