Em Haskell tudo começa pelas tipagens e dados que você precisa. Primeiramente certifique-se que tenha instalado o cabal
ou stack
para criar projetos em Haskell.
Criando projeto
Para criar o projeto é simples
$ cabal init -n tracer
O cabal irá criar um projeto de modo interativo (bem como o npm init
).
Tipos e dados
Primeiro precisamos definir o que será cada coisa, os componentes e a implementação.
Na estrutura temos o que chamaremos de ISO ou EDIO (Estrutura de instrumentação da observabilidade) que é nada mais que um mapa chave-valor, onde a chave é a ação originária e o valor é a uma lista de ações possíveis (ou ações alvos possíveis).
module Instrumentation () where
newtype ISO = ISO [(String, [String])] deriving (Eq, Show)
O Map, bem utilizado em outras linguagens, se resume a uma lista de tuplas com apenas 2 valores, a chave e o valor em si. E pra isso teremos que criar algumas funções auxiliares para inserir, procurar ou deletar entradas nesse mapa.
Funções auxiliares
No caso, por agora, precisamos ter uma função para criar um ISO vazio e um para inserir.
newISO :: ISO
newISO = ISO []
A função de criação é bem simples pois só precisamos ter uma função que usa o método construtor ISO
com uma lista vazia.
insert :: (String, [String]) -> ISO -> ISO
insert (key, value) (ISO items) = ISO newIso
where
newIso = items ++ [(key, value)]
A função de inserção seria apenas a concatenação da lista anterior com uma lista nova. Em Haskell, podemos ter N formas de criar essa função, usei a notação where
, pois ela nos dá uma forma mais fácil de compreender o que é cada parte da função. Nesse caso eu separei a concatenação de listas numa variável desse where
para facilitar a legibilidade da função em si.
Testes, pois sem testes não viveríamos
Em Haskell, testes são feitos por, acredite ou não, funções! Essas funções podem ser escritas de várias maneiras mas aqui usarei o mais comum na comunidade, que é o HUnit.
Primeiro nós instalamos o HUnit pelo cabal.
$ cabal install --lib HUnit
E precisamos alterar no nosso arquivo tracer.cabal
test-suite tracer-test
import: warnings
default-language: Haskell2010
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Main.hs
other-modules: InstrumentationTest -- novo
build-depends:
base ^>=4.18.0.0,
tracer,
HUnit -- novo
Nesse arquivo adicionamos um novo módulo além do Main que o cabal cria para nós, e o que depende do build desse teste.
Teste da estrutura ISO
Com isso precisamos criar os testes nesse arquivo test/InstrumentationTest.hs
module InstrumentationTest () where
import Instrumentation (ISO (..), insert, newISO)
import Test.HUnit
createNewISOTest :: Test
createNewISOTest = TestCase (assertEqual "should return empty ISO" (ISO [] newISO)
insertEntryTest :: Test
insertEntryTest = TestCase (assertEqual "should return a ISO with entry" desired appliedFunction)
where
desired = ISO [("chave", ["valor1"])]
appliedFunction = insert ("chave", ["valor1"]) newISO
Nesse arquivo criamos tanto o teste para checar a criação de uma nova ISO e a inserção de uma entrada. E agora precisamos colocar ele no arquivo test/Main.hs
module Main (main) where
import Test.HUnit
import InstrumentationTest (createNewISOTest, insertEntryTest)
import qualified System.Exit as Exit
tests :: Test
tests = TestList [TestLabel "createNewISO" createNewISOTest, TestLabel "insertEntryTest" insertEntryTest]
main :: IO ()
main = do
result <- runTestTT tests
if failures result > 0 then Exit.exitFailure else Exit.exitSuccess
Nesse arquivo nós criamos uma suite de testes para que ele rode todos os testes do módulo InstrumentationTest
Para rodar os testes apenas rodamos
$ cabal test
E ele terá um resultado parecido com esse (além dos logs de build)
Test suite eyaara-test: RUNNING...
Cases: 2 Tried: 2 Errors: 0 Failures: 0
Test suite tracer-test: PASS
E por hoje é só! Nessa série de artigos eu irei recriar o sistema e estrutura que desenvolvi baseado no algoritmo Drain para parsing de logs.
Top comments (2)
O primeiro artigo direto ao ponto que vejo sobre haskell, muito foda! Vlw pelo conteúdo
Conteúdo incrível, Roque! Parabéns mano! 💯