Estou tentando fazer uma função que calcule o fatorial de um número. Está marcando um erro na tarefa e não sei como corrigir.
for list action = mapM_ action list
main :: IO Int
main = do
x <- getLine
for [1..read x] (\ i -> do
let tmp = 0
tmp <- tmp*i
)
return (tmp)
Haskell é uma linguagem funcional. Um dos aspectos de tais linguagens é que as variáveis são imutáveis : uma vez atribuído um valor, você nunca poderá alterar esse valor.
Como resultado, Haskell não possui
for
loops embutidos, etc. Seu "burro de carga" é a recursão : recorremos até que um determinado valor seja determinado. Para o caso fatorial, será assim:e então o principal pode ser parecido com:
ou mais curto:
Primeiro, uma observação sobre loops. Eu vou assumir
for_
. Haskell não possui nenhuma palavra-chave de loop, mas seu paradigma mônada é suficientemente flexível para que possam ser implementados apenas como funções de biblioteca.No entanto, Haskell não possui variáveis mutáveis. Então, algo assim
tmp <- tmp*i
nunca pode fazer sentido.(NB, você pode realmente escrever
let tmp = tmp*i
, mas não faça isso. Não realiza nada de útil; em vez de atualizar a variável, ele define uma variável, mas com uma definição circular sem sentido referindo-se ao seu próprio resultado, ou seja, este é apenas um não-terminal computação.)Ok, isso sobre não ter variáveis mutáveis não é bem verdade. Eles também estão disponíveis na biblioteca padrão, são chamados
IORef
s . Eles não podem ser atualizados com<-
ou=
sintaxe, mas com asIO
ações definidas noData.IORef
módulo. O seguinte funciona:Observe que não há
return
. Em Haskell,return
não é uma palavra-chave ( notou um tema? ) mas simplesmente uma função que injeta um valor puro (neste caso anInt
) em uma ação monádica (neste casoIO Int
). Mas ler oIORef
já é uma ação impura, portanto você deve simplesmente usá-lo como a última linha.Retornar um valor de
main
não é o que você provavelmente deseja (o valor de retorno é ignorado); Acho que você pretendia imprimi-lo:Tudo bem, essa é a solução literal para o seu problema.
No entanto , é altamente recomendável não usar
IORef
para algo assim. Geralmente toda a filosofia de Haskell é evitar efeitos colaterais como mutação. Em vez disso, você deve definir sua função por recursão e usá-la apenasIO
no final para imprimir o resultado completo. Há uma infinidade de exemplos disso, um exemplo bem-humorado é The Evolution of a Haskell Programmer .