unlocker quiere que puedo programa porque para encuentra eliminar dejan como carpetas borrar archivos archivo haskell

haskell - quiere - Eliminar archivo si existe



programa para eliminar carpetas que no se dejan borrar (2)

¿Cuál es la forma correcta de hacer esto en Haskell?

if exists "foo.txt" then delete "foo.txt" doSomethingElse

Hasta ahora tengo:

import System.Directory main = do filename <- getFileNameSomehow fileExists <- doesFileExist filename if fileExists then removeFile filename ??? doSomethingElse


( Nota: la respuesta de ehird hace un muy buen punto con respecto a una condición de carrera. Debe tenerse en cuenta al leer mi respuesta, lo cual ignora el problema. Tenga en cuenta también que el pseudocódigo imperativo presentado en la pregunta también tiene el mismo problema. .)

¿Qué define el nombre de archivo? ¿Se incluye en el programa o es suministrado por el usuario? En tu imperativo pseudocódigo, es una cadena constante en el programa. Asumiré que desea que el usuario lo proporcione pasándolo como el primer argumento de la línea de comandos al programa.

Entonces sugiero algo como esto:

import Control.Monad import System.Directory import System.Environment doSomethingElse :: IO () main = do args <- getArgs fileExists <- doesFileExist (head args) when fileExists (removeFile (head args)) doSomethingElse

(Como puede ver, agregué la firma de tipo doSomethingElse para evitar confusiones).

getArgs System.Environment para la función getArgs . En caso de que el archivo en cuestión esté dado simplemente por una cadena constante (como en su imperativo pseudo-código), simplemente elimine todas las cosas de args y complete la cadena constante donde sea que tenga head args .

Control.Monad se importa para obtener la función when . Tenga en cuenta que esta función útil no es una palabra clave (como if ), sino una función ordinaria. Veamos su tipo:

when :: Monad m => Bool -> m () -> m ()

En su caso, m es IO , por lo que puede pensar when es una función que realiza una acción Bool y IO y realiza la acción solo si Bool es True . Por supuesto, usted podría resolver su problema con if , pero en su caso when lee mucho más claro. Al menos eso pienso.

Anexo: Si usted, como lo hice al principio, tiene la sensación de que when trata de una maquinaria mágica y difícil, es muy instructivo tratar de definir la función usted mismo. Te lo prometo, es muerto simple ...


Sería mejor eliminar el archivo y simplemente recuperarlo si no existe:

import Prelude hiding (catch) import System.Directory import Control.Exception import System.IO.Error hiding (catch) removeIfExists :: FilePath -> IO () removeIfExists fileName = removeFile fileName `catch` handleExists where handleExists e | isDoesNotExistError e = return () | otherwise = throwIO e

Esto evita la condición de carrera de alguien que borra el archivo entre su código para verificar si existe y lo elimina. Puede que no importe en su caso, pero es una buena práctica de todos modos.

Tenga en cuenta la línea de import Prelude hiding (catch) de import Prelude hiding (catch) : esto se debe a que Prelude contiene funciones más antiguas del manejo de excepciones que ahora están en desuso a favor de Control.Exception, que también tiene una función llamada catch ; la línea de importación simplemente oculta la catch de Prelude a favor de Control.Exception .

Sin embargo, eso aún deja su pregunta subyacente más fundamental: ¿cómo se escriben los condicionales en IO ?

Bueno, en este caso, bastaría con hacer

when fileExists $ removeFile filename

(utilizando Control.Monad.when ). Pero es útil aquí, como suele ser en Haskell, mirar los tipos.

Ambas ramas de un condicional deben tener el mismo tipo. Así que para completar

if fileExists then removeFile filename else ???

debemos mirar el tipo de removeFile filename ; lo que sea ??? Es decir, tiene que tener el mismo tipo.

System.Directory.removeFile tiene el tipo FilePath -> IO () , por lo que removeFile filename tiene el tipo IO () . Entonces, lo que queremos es una acción IO con un resultado de tipo () que no haga nada.

Bueno, el propósito del return es construir una acción que no tenga efectos, y simplemente devuelva un valor constante, y el return () tiene el tipo correcto para esto: IO () (o más generalmente, (Monad m) => m () ). Entonces ??? is return () (que puede ver que usé en mi fragmento de removeFile mejorado arriba, para no hacer nada cuando removeFile falla porque el archivo no existe).

(Por cierto, ahora deberías poder implementar when con la ayuda de return () ; es muy simple :))

No se preocupe si al principio le resulta difícil entrar en la forma de las cosas de Haskell: llegará con naturalidad en el tiempo y, cuando lo haga, será muy gratificante. :)