Nós escrevemos "Olá, mundo!" Aplicativo da web Haskell (Spock)

Eu estava cansado de escrever em Python, queria algo incomum. Eu decidi tentar Haskell. Não conheço o idioma, mas não queria escrever programas de treinamento para console, como calcular fatorial. Depois de estudar um número bastante grande de postagens sobre Haskell e sua aplicação na vida real, percebi que um dos pontos em potencial do crescimento da popularidade do idioma é escrever aplicativos da Web. Curiosamente, existem algumas estruturas da Web sob Haskell. Minha escolha recaiu sobre Spock , porque, a julgar pela descrição, é uma estrutura simples e rápida de se desenvolver. Tenho alguma experiência em escrever aplicativos da Web no Flask, então pensei que seria interessante comparar abordagens diferentes para resolver problemas semelhantes. Neste artigo, tentarei apresentar minha maneira mais detalhada de tentativa e erro no aprendizado do Haskell escrevendo um aplicativo da Web elementar no Spock. Talvez isso seja útil para quem duvida de tentar estudar Haskell e se será útil na vida real.


Um pouco sobre Haskell e como cozinhá-lo


A primeira coisa que todo desenvolvedor enfrenta ao aprender um novo idioma é escolher e configurar um ambiente de desenvolvimento. Obviamente, você pode escrever em um caderno, mas se você tiver pelo menos alguma experiência no desenvolvimento de projetos de produção, esse método causará dor. A propósito, Haskell é uma linguagem bastante antiga e comum e suporta os editores e ide mais famosos. Meu amigo Haskellist usa emacs. Estou acostumado com o IDE normal, então instalei o plugin para IntelliJ.


Além disso, para o desenvolvimento, você precisa da pilha , que agora é o padrão e combina um compilador, um sistema de gerenciamento de pacotes, um sistema de compilação e teste.


Tudo parece bastante amigável, não houve problemas com a instalação. Para o desenvolvimento, eu uso o Mac OS, não testei em outros sistemas, mas suspeito que no Linux tudo será iniciado sem problemas.


Olá mundo!


Preparação


Vamos ao tutorial e tentamos fazer tudo de acordo com as instruções. Lá, eles sugerem a criação de um projeto padrão através da pilha: stack new MyLovelyProlect . O projeto padrão é uma pasta com três subpastas: app , src , test . Parece bastante lógico: uma pasta para o aplicativo principal, uma para funções auxiliares e a terceira para testes. Como escrevemos "Olá, mundo!", Não precisamos das pastas src e de test , mas não precisamos excluí-las, pois, caso contrário, precisaremos limpar cuidadosamente outros arquivos, por exemplo, HelloWorld.cabal .


Na verdade, o código


Além disso, no tutorial, propõe-se copiar algum código em Main.hs Vamos simplificar um pouco mais para comparar com o que o balão oferece.


 {-# LANGUAGE OverloadedStrings #-} module Main where import Web.Spock import Web.Spock.Config app :: SpockM () () () () app = get root $ text "Hello World!" main :: IO () main = do cfg <- defaultSpockCfg () PCNoDatabase () let mw = spock cfg app runSpock 8080 mw 

Para comparação, darei o mesmo código no balão:


 from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" app.run() 

Pelo número de linhas, o frasco ainda ganha: 8 versus 13. Mas, considerando que Haskell é uma linguagem de tipo estaticamente e duas linhas ocupam a determinação de tipo, a diferença, na minha opinião, é pequena. Pelo menos o código acima não me assustou de continuar aprendendo o idioma.


Montagem e lançamento


Em seguida, vá para HelloWorld.cabal e adicione o executable HelloWorld-exe à seção build-depends: line Spock >=0.13 . No tutorial do site, propõe-se incluir mais 2 dependências, mas para meus propósitos elas ainda não são necessárias. Se agora tentarmos criar o aplicativo usando a stack build --fast --pedantic , obteremos o seguinte erro:


 Error: While constructing the build plan, the following exceptions were encountered: In the dependencies for HelloWorld-0.1.0.0: Spock must match >=0.13, but the stack configuration has no specified version (latest matching version is 0.13.0.0) needed since HelloWorld is a build target. Some different approaches to resolving this: * Consider trying 'stack solver', which uses the cabal-install solver to attempt to find some working build configuration. This can be convenient when dealing with many complicated constraint errors, but results may be unpredictable. * Recommended action: try adding the following to your extra-deps in /Users/dkvasov/Documents/Haskell/Spock/HelloWorld/stack.yaml: Spock-0.13.0.0@sha256:8115862eb4fb84a26fb7bcd34f30acf036bd2e7c4eaf813c185c5562d138bba2 Plan construction failed. 

É bem claro: a pilha não sabe qual versão do Spock precisa ser instalada; portanto, ela deve ser gravada no arquivo stack.yaml . Adicione extra-deps e tente construir novamente. Outros erros semelhantes aparecerão e, como resultado, no arquivo stack.yaml , obtive o seguinte:


 extra-deps: - Spock-0.13.0.0 - Spock-core-0.13.0.0 - reroute-0.5.0.0 - stm-containers-0.2.16 - focus-0.1.5.2 

Depois disso, tudo se juntou. Meus artefatos de coleção estavam na .stack-work/dist/x86_64-osx/Cabal-2.4.0.1/build .


Tudo começou com o stack exec HelloWorld-exe comandos stack exec HelloWorld-exe , e no localhost:8080 eu vi o bem-vindo "Olá, mundo!". Não era necessário dançar com um pandeiro.


Estamos tentando descobrir o que está acontecendo.


Até o momento, não usamos nenhum conhecimento específico de programação funcional (FP) e da linguagem Haskell. Utilizamos o bom senso e o conhecimento dos princípios básicos do desenvolvimento. Você não pode continuar assim. Para um maior entendimento, precisamos saber algumas coisas sobre a FA. AF não é o antípode do OOP. Aqueles familiarizados com a linguagem Scala sabem que esses dois conceitos coexistem facilmente. O antípode do FP é uma programação imperativa. Enquanto o modelo funcional de cálculos se baseia na composição de funções, o modelo imperativo se baseia no processo de mudanças sucessivas nos estados do sistema. Daqui se conclui que em linguagens puramente funcionais como Haskell, supõe-se que as funções sejam "puras", ou seja, elas não contêm um estado mutável e "efeitos colaterais", além do valor de retorno. Isso facilita a criação de composições de recursos. Na verdade, o requisito de "pureza" impõe muitas restrições ao uso de linguagens funcionais no mundo real. No entanto, como existem aplicativos de produção no Haskell, você ainda pode, de alguma forma, usar funções puras no mundo real. Vamos dar uma olhada em nossos Main.hs


Pelo que entendi, o aplicativo é uma variável do tipo SpockM , que é uma mônada . Provavelmente, se você não estiver familiarizado com o estilo funcional da programação e da teoria das categorias, não entenderá pela primeira vez o que é e por que precisa. No entanto, é necessário lidar com isso pelo menos no nível básico, uma vez que as mônadas são a base para a aplicação da linguagem Haskell. Existem muitos artigos com vários graus de detalhes sobre esse assunto, inclusive sobre Habré. Claro, não vou trazê-los aqui. Até agora, proponho considerar que as mônadas são tão mágicas que permitem produzir os chamados efeitos colaterais. Há outra mônada em nossa aplicação: IO . Seu efeito colateral é a entrada / saída de dados.


O SpockM é parametrizado por outros quatro tipos. Eles correspondem ao valor da conexão, sessão, estado e retorno do banco de dados. Para um aplicativo vazio, nada disso é necessário; portanto, sempre usaremos o tipo () , chamado Unidade. Dentro do app vinculamos caminhos para ações. Nesse caso, determinamos o caminho base / e a ação "Hello, world! get- .


Em seguida, criamos uma configuração padrão e a atribuímos ao cfg . Em seguida, usando a função spock crie middleware para o aplicativo e cfg e transfira-o para o runSpock junto com a porta de inicialização desejada.


Conclusão


É claro que tudo descrito aqui é muito simples, e todos que falam inglês e estão equipados com um cérebro poderão fazer o mesmo observando o tutorial inicial do spock. Este artigo foi mais sobre como eu me familiarizei com a linguagem Haskell. O que vem a seguir? Além disso, quase todos os recursos de aprendizado sugerem o uso de state e a escrita de um aplicativo de tarefas, conectando o banco de dados e ... Talvez no futuro eu escreva uma sequência.


Referências


Source: https://habr.com/ru/post/pt449628/


All Articles