Pergunta

Eu escrevi uma função Haskell que calcula o fatorial de cada número em uma determinada lista e a imprime na tela.

factPrint list =
if null list
    then putStrLn ""
    else do putStrLn ((show.fact.head) list)
        factPrint (tail list)

A função funciona, mas acho a terceira linha um pouco confusa. Por que o compilador (GHC) não relatou um erro, pois não há "fazer" antes da função "putstrln" (quase?)? Se eu omito "faça" da 4ª linha, um erro surge conforme o esperado.

Eu sou muito novo em Haskell e seus caminhos, então, por favor, me perdoe se eu dissesse algo excessivamente bobo.

Foi útil?

Solução

do putStrLn ((show.fact.head) list)
   factPrint (tail list)

na verdade é outra maneira de escrever

putStrLn ((show.fact.head) list) >> factPrint (tail list)

que, por sua vez, significa

putStrLn ((show.fact.head) list) >>= \_ -> factPrint (tail list)

o do A notação é uma maneira conveniente de reunir essas mônadas, sem essa outra sintaxe feia.

Se você tiver apenas uma declaração dentro do do, então você não está amarrando nada, e o do é redundante.

Outras dicas

Se você é novo em Haskell, pense em do semelhante ao aparelho necessário depois if em uma linguagem do tipo C:

if (condition)
  printf("a"); // braces not required
else {
  printf("b"); // braces required
  finish();
}

do Funciona da mesma maneira em Haskell.


Talvez ajude a olhar para o tipo de fatrint e, em seguida, refatorar para usar a correspondência de padrões:

factPrint :: [Int] -> IO ()
factPrint [] = putStrLn ""
factPrint list = do
  putStrLn (show.fact.head) list
  factPrint (tail list)

Então, se o FactPrint retornar IO (), e o tipo de putStrLn "" é IO (), então é perfeitamente legal para factPrint [] para igual putStrLn "". Não do Necessário-no fato, você pode apenas dizer factPrint [] = return () Se você não queria a nova linha de fundo.

do é usado para unir múltiplas expressões monádicas. Não tem efeito quando seguido por apenas uma única expressão.

Para o IF para ser bem formado, é necessário apenas que a cláusula e a cláusula mais tenham o mesmo tipo. Já que ambas as cláusulas têm o tipo IO () este é o caso.

A palavra-chave DO é usada para sequenciamento, um if-then-else em haskell não precisa conter um do Se cada ramificação for uma única declaração, por exemplo.

if a
  then b
  else c

Você precisa do do No seu exemplo, pois você está sequenciando duas operações em sua filial. Se você omitir o do então o factPrint(tail list) A declaração é considerada não fazer parte da função e, portanto, o compilador reclama, pois encontrou uma declaração inesperada.

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