- Flix é uma linguagem inovadora que combina programação funcional com um modelo orientado a efeitos
- Facilita a modelagem de regras lógicas e dependências de dados, com destaque para a expressão declarativa de conhecimento
- Permite escrever em código, de forma concisa, relações de dependência e fluxos de processo complexos
- Essa abordagem oferece eficiência em tarefas de projeto de algoritmos e inferência
- Com recursos de consulta, é possível explorar facilmente dados baseados em conhecimento
Visão geral da linguagem Flix
- Flix é uma nova linguagem funcional que adota o paradigma de programação orientado a efeitos
- Em vez de código procedural, o programador pode descrever sistemas com foco em relações lógicas e regras
- Com regras lógicas (declaradas dentro de
#{}), é possível expressar de forma concisa cenários complexos de manufatura, como componentes, dependências, tempo de montagem e prazo de entrega
Regras declarativas e modelagem de dados
- No código de exemplo, são usados fatos e regras como PartDepends, AssemblyTime, DeliveryDate, ReadyDate
- Define relações de dependência entre produtos, como em
PartDepends("Car", "Chassis")
- Define o tempo de montagem por peça, como em
AssemblyTime("Engine", 2)
- Também explicita o prazo de entrega das peças, como em
DeliveryDate("Piston"; 1)
- Por meio da regra lógica ReadyDate, é possível calcular a data final de disponibilidade tanto de peças com prazo de entrega definido quanto de peças montadas
- Em outras palavras, é possível inferir de forma simples o ciclo de fornecimento e montagem de cada componente
Inferência orientada a efeitos e consultas
- O mecanismo de regras lógicas do Flix combina orientação a efeitos com transparência referencial, incentivando o projeto de programas mais intuitivos e com menos erros
- Usando a sintaxe de consulta, é fácil obter a data de disponibilidade de todas as peças correspondentes a ReadyDate
- Essa abordagem pode ser aplicada em diversas áreas, como manufatura, gestão da cadeia de suprimentos e automação baseada em inferência
Resumo e vantagens
- Flix combina efeitos (Effects) e inferência baseada em regras lógicas para modelar de forma concisa as relações entre componentes e processos em sistemas complexos
- Em comparação com linguagens tradicionais, oferece vantagens em clareza lógica e concisão do código
- Pode oferecer uma solução adequada para diversos problemas modernos de software, como grafos de conhecimento, motores de workflow e inferência de dados
1 comentários
Comentários do Hacker News
Fiquei profundamente impressionado com a profundidade e a abrangência dessa linguagem.
Tipos de dados algébricos, programação lógica, mutabilidade e outros recursos essenciais já vêm incluídos desde o primeiro momento.
O que mais me agradou ao ver a tabela comparativa foi o fato de um único executável desempenhar os papéis de gerenciador de pacotes, LSP e compilador.
No caso de Haskell, o LSP precisava reimplementar muita coisa entre o
ghce os arquivoscabal, e ainda havia ostack, então a oficialidade do gerenciador de pacotes era um pouco ambígua.Não é minha intenção criticar Haskell; é realmente uma linguagem excelente.
Mas acho uma pena que seus melhores recursos estejam um pouco escondidos.
Fico curioso sobre quão confortavelmente o Flix se integra com Java e outras tecnologias na JVM.
Como os compiladores da JVM apagam a maior parte das informações de tipo, considero positivo que o conceito de
regionsdo Flix dê suporte de primeira classe à interação imperativa.Usar a JVM também traz a enorme vantagem de poder aproveitar facilmente bibliotecas padrão de altíssima qualidade, que valem bilhões de dólares.
Por isso, acho que JVM ou .net core são a escolha mais sensata em mais de 90% dos projetos.
F# parece ser a única linguagem realmente comparável.
Seria ótimo ter um documento que resumisse as limitações da interoperabilidade entre Flix e JVM.
Para referência, há informações relacionadas aqui.
Basicamente, valores Flix/Java passam por boxing/unboxing.
Além disso,
Recordé um cidadão de primeira classe.Se você gosta da ideia de o gerenciador de pacotes, o LSP e o compilador serem todos um único executável, provavelmente também vai gostar bastante de Unison.
A parte de programação lógica e
datalogparece meio adicional.Os outros recursos claramente aumentam a segurança de tipos da base de código, mas programação lógica é algo bem de nicho, então talvez fosse melhor existir separadamente da linguagem.
Não é totalmente correto dizer que compiladores da JVM apagam toda a informação de tipo (no caso de classes anônimas, os parâmetros de tipo são mantidos).
Também existem várias soluções de contorno.
E, na verdade, do ponto de vista do compilador isso não é um grande problema.
Basta aleatorizar o nome da classe com o construtor de tipo aplicado e renderizá-la como uma classe comum.
F# ainda não oferece suporte a type classes, então há muitas limitações para programação baseada em monads.
Se F# pulasse o estilo de monads à la Haskell e fosse direto para efeitos algébricos, acho que isso combinaria mais com a filosofia do F#.
A parte de
StringBuilderme decepciona um pouco.Nesse aspecto, parece pender mais para o lado do Java, e isso me deixa em dúvida.
Fora isso, à primeira vista parece bom.
Do ponto de vista da semântica da linguagem, a semântica de extensão/restrição de registros polimórficos parece seguir o esquema de labels com escopo de Leijen (link do artigo).
Por exemplo, se existe um registro
r1 = { color = "yellow" }, ele pode ser estendido parar2 = { +color = "red" | r1 }.r2#colorresulta em"red", e se o campo"color"for removido novamente, temosr3 = { -color | r2 }.r3#colorentão volta ao valor original,"yellow".Acho isso muito mais razoável do que o estilo anterior, que usava um sistema de tipos extremamente complexo para impedir que o mesmo campo com a mesma label fosse adicionado duas vezes.
Fico curioso sobre por que Aarhus (especialmente a universidade/o polo tecnológico) tem uma influência tão forte em pesquisa de linguagens de programação.
C++, C#/Typescript, Dart e outras têm raízes fortes nessa pequena região da Dinamarca.
Não é uma universidade tradicionalmente de elite como Ivy League ou Oxbridge, nem um lugar como Delft ou INRIA.
O que a tornou tão especial? É a água ou existe algum outro motivo? É só curiosidade mesmo.
Só para pontuar uma coisa: C# foi criado por Anders Hejlsberg, e ele estudou na DTU (Copenhague).
Turbo Pascal também foi criado por ele, e a Borland também foi fundada por um dinamarquês.
De modo geral, a Dinamarca é forte em teoria de linguagens de programação.
Por exemplo, o livro-texto padrão de pós-graduação em análise estática de programas (de Nielson & Nielson) também é de autores dinamarqueses.
Mads Tofte teve grande contribuição para Standard ML.
Aarhus pode não estar no nível de Ivy League ou Oxbridge, mas é uma excelente universidade.
Na Europa existem dezenas de universidades assim, com fama menor, mas altíssima qualidade em ensino e pesquisa.
Aarhus tem uma tradição forte em lógica, teoria dos tipos e linguagens funcionais/orientadas a objetos.
Muitos pesquisadores influentes dessas áreas vieram de Aarhus.
Além disso, a pesquisa em linguagens de programação parece sofrer bastante com um viés pró-EUA no cenário global.
Instituições como Aarhus tendem a investir muito menos em marketing ou autopromoção e mais em pesquisa de qualidade.
Não quer dizer que sejam melhores ou piores, mas isso dificulta receber atenção global.
O Flix continua me impressionando como a linguagem mais cuidadosamente projetada entre as da família ML.
A combinação dos paradigmas funcional, imperativo e lógico, junto com um sistema polimórfico de tipos e efeitos e restrições em Datalog, todos como cidadãos de primeira classe, é realmente única.
A separação rigorosa entre código puro e impuro no nível de tipos parece uma alternativa refrescante aos Monads, mais fácil de inferir em termos de efeitos.
A filosofia de “uma linguagem, sem flags necessárias” e a busca por apenas erros em tempo de compilação também são simples e previsíveis.
Mesmo sem a JVM oferecer eliminação de recursão de cauda nativamente, o fato de o Flix implementar eliminação completa de chamadas em cauda é um feito técnico notável.
Tenho curiosidade sobre a experiência de quem usa Flix em produção ou em pesquisa.
Especialmente em programação lógica ou concorrência, gostaria de ouvir sobre dificuldades com a “closed-world assumption”, a falta de suporte a exceções e as diferenças em relação à integração de Datalog com outras linguagens lógicas como Prolog.
Quando vi Flix pela primeira vez, achei tão interessante que até escrevi um texto chamado “Flix for Java Programmers”.
Hoje ele já está um pouco desatualizado e precisaria de revisão, mas...
Se alguém tiver interesse, pode ver aqui.
O post do blog é realmente muito bom.
Se você permitir, seria ótimo adicioná-lo à coletânea oficial de posts do blog do Flix (link).
Desde então, a linguagem Flix evoluiu bastante.
Em especial, o sistema de efeitos foi bastante expandido, houve melhorias na interoperabilidade com Java e atualizações de sintaxe.
O blog parece um verdadeiro tesouro.
Dá a sensação de ser uma versão mais refinada de ideias que me incomodam há muito tempo.
Estou animado para ler tudo.
É legal que também suporte HKTs.
Mas não vejo explicação sobre typeclass, então fiquei curioso.
Se também tivesse suporte a typeclass e macros no estilo Scala, eu até tentaria portar minhas bibliotecas (
distage,izumi-reflect,BIO) para Flix e consideraria seriamente migrar de Scala para Flix.Depois percebi que futuramente typeclass é chamado de trait.
Fico curioso sobre as macros.
Também achei uma pena o Flix não oferecer herança nominal explícita.
Nem mesmo a forma mais inofensiva de
traitem Scala é permitida.Typeclass não substitui interfaces, e sem essa abstração sinto que muitos recursos úteis simplesmente não podem ser implementados, ou então o código fica feio.
trait) junto com HKT, associated type e associated effect.traittambém pode fornecer implementações padrão de funções, mas elas podem ser sobrescritas nas instâncias.Flix não tem herança (
inheritance) de forma alguma.traité usado apenas em tempo de compilação e passa por monomorphization, então não há overhead em tempo de execução.O inliner do Flix também otimiza o interior dos
traite elimina closures agressivamente.Por exemplo, funções de ordem superior ou pipelines acabam se transformando em loops comuns no nível de bytecode, sem alocação de closure nem indireção.
Flix ainda não oferece suporte a macros.
Talvez por causa de experiências de (mau) uso em outras linguagens, há receio em introduzi-las.
Estamos procurando novos autores de bibliotecas, então, se tiver interesse, passe no canal do Gitter.
Sobre a seção “recursos que o Flix não suporta” na documentação oficial:
existe um item chamado “No Code Before Main”.
Mas a explicação real diz: “Flix não executa nenhum código antes de
maine não existe nada como inicializador estático”.Acho que o nome do recurso seria mais preciso como “Code Before Main”.
Fico curioso sobre por que o Flix exige marcar explicitamente quando uma função é pura.
Parece que, na maioria dos casos, análise estática bastaria para inferir isso, então queria entender o motivo.
Pelo que sei, quando você marca a pureza de uma função, o compilador garante isso.
Ao ler a frase “Flix rastreia com precisão a pureza de todas as expressões do programa” e ver exemplos de definição de função sem marcação de pureza/impureza,
fiquei com a impressão de que, na maioria dos casos, o compilador consegue inferir a pureza automaticamente, então essa marcação poderia ser opcional.
O FAQ do Flix (link) começa normal e vai ficando cada vez mais engraçado.
Alguns exemplos divertidos:
Fico curioso se agentes de código compatíveis com essa linguagem funcionam bem, ou se ainda é um caso de precisar pensar com a própria cabeça.
Falo meio em tom de brincadeira, mas é triste porque a linguagem parece muito interessante.
Tenho a impressão de que os LLMs podem acabar atrapalhando a adoção de linguagens novas, e me pergunto como resolver isso.
Eu, na verdade, tenho a intuição oposta: LLMs vão reduzir a barreira de adoção de novas linguagens.
O código da biblioteca padrão já é suficiente para um LLM aprender uma sintaxe nova e, mesmo que não seja, um agente pode observar a saída do compilador e aprender com isso.
O trabalho de portar código em si não exige tanta criatividade; é uma tarefa bem definida e deve ser uma das primeiras áreas de automação por LLM.
Daqui para frente, nós é que vamos precisar pensar seriamente com o próprio cérebro sobre “por que estamos fazendo isso” e “que impacto isso tem no mundo”.
Coloquei no prompt a instrução de usar obrigatoriamente tipos indexados/dependentes de Idris, e os resultados foram bons.
(Sem esse tipo de instrução, o limite costuma ser algo como GADT.)