Tenho esse pseudocódigo que calcula o fatorial de um número fornecido pelo usuário.
Process without_title
Define i, tmp, x As Integers;
tmp<-1;
Write "Enter a number to calculate its factorial";
Read x;
For i <- 1 Until x Do
tmp<-tmp * i;
EndTo
Write tmp;
EndProcess
Agora eu gostaria de implementar o mesmo código em Haskell usando compreensões de lista
import Data.IORef
factorial::Int -> Int
factorial x = [tmp|i<-[1..x], modifyIORef tmp (*i)]
Lança erro dizendo tmp
variável não definida
Como defino a tmp
variável para poder utilizá-la?
Para implementar uma função fatorial usando um mutável
IORef
como este, você precisará trabalhar na mônada IO e usar umanewIORef
operação para criar suaIORef
e, em seguida, usarforM_
,traverse_
,sequence_
ou uma função semelhante para sequenciar um conjunto de operações IO nessa funçãoIORef
. Pode ser algo como:ou, se você preferir usar uma compreensão de lista para que fique um pouco mais parecida com sua tentativa acima, algo como:
(Usar o strict
modifyIORef'
fornece melhor desempenho do que o lazymodifyIORef
.)Isso pode então ser chamado assim:
Geralmente, isso será mais lento do que uma solução mais direta e "pura", como:
Meus benchmarks sugerem que a
IORef
versão baseada em - é cerca de duas vezes mais lenta que aproduct
versão baseada em - pura.Bem, é muito anti -Haskellish trabalhar com variáveis mutantes. Esta é uma das razões pelas quais você precisará trabalhar com
IO Ref
s: já que o ref em si não muda, e modificar seu valor é visto como um efeito colateral.Se você deseja implementar o fatorial manualmente, a recursão é usada como forma de repetir uma determinada tarefa, e ao passar valores diferentes para o parâmetro pode ser visto como realizando esta iteração com valores modificados, então:
Mas como Haskell possui algumas funções utilitárias de nível superior, podemos, por exemplo, gerar uma lista de itens e então determinar o produto deles.