list haskell is-empty empty-list

¿Por qué usar la función nula en lugar de==[] para verificar la lista vacía en Haskell?



is-empty empty-list (4)

Estoy leyendo el capítulo "Comenzando" de Learn You a Haskell for Great Good! . Dice:

null comprueba si una lista está vacía. Si lo es, devuelve True , de lo contrario devuelve False . Use esta función en lugar de xs == [] (si tiene una lista llamada xs )

Lo intenté en Ghci:

xs = [] -- and then, xs == [] null xs

Ambos son True .

Me pregunto cuál es la diferencia.

¿Debo usar la función null lugar de == [] y por qué?


Además de las buenas respuestas dadas hasta ahora, null realidad tiene tipo

null :: Foldable t => t a -> Bool

No sé si ha llegado a las clases de tipos en LYAH, pero el problema es que null se puede usar no solo para listas, sino para cualquier estructura de datos que implemente null .

Esto quiere decir que el uso de null en un Map o en un Set es válido.

> null Map.empty True > null (Map.singleton 1) False > null Set.empty True > null (Set.singleton 1) False > null [] True > null [1] False

No creo que sea especialmente común escribir funciones que deban ser tan generales, pero no se pierde nada con escribir código más general.

Una nota al margen

En muchos casos, terminará queriendo usar una función como null para realizar un comportamiento condicional en una lista (u otra estructura de datos). Si ya sabe que su entrada es una estructura de datos específica, es más elegante simplemente hacer coincidir el patrón en su caja vacía.

Comparar

myMap :: (a -> b) -> [a] -> [b] myMap f xs | null xs = [] myMap f (x:xs) = f x : myMap f xs

a

myMap'' :: (a -> b) -> [a] -> [b] myMap'' f [] = [] myMap'' f (x:xs) = f x : myMap'' f xs

En general, debe intentar preferir la coincidencia de patrones si tiene sentido.


Hay una diferencia. Para utilizar x == [] , el tipo de los elementos de la lista debe ser un miembro de la clase de tipos Eq . De hecho, la declaración de instancia define la verificación de la igualdad de dos listas:

instance Eq a => Eq [a] where [] == [] = True (x:xs) == (y:ys) = x == y && xs == ys _ == _ = False

Eso significa que no puede usar x == [] si x es, por ejemplo, una lista de IO Int s.

null :: [a] -> Bool por otro lado, usa la coincidencia de patrones. Esto se implementa como :

null :: [a] -> Bool null [] = True null (_:_) = False

Entonces, independientemente del tipo de elementos de la lista, siempre se verificará.


También una función simple que filtre toda la lista vacía fallaría:

withoutEmpty = filter (== [])

y eso sería:

withoutEmpty = filter null

Darse cuenta de:

withoutEmpty ls = filter (==[]) ls

Funcionará bien, pero el punto importante es que en algunos casos, como el otro, podría fallar.

También mire a @cole answer, que complementa todas las respuestas aquí, el typeclass Foldable tiene la función null que hay que implementar:

Para ver más información de Foldable aquí.


Usted debe utilizar null . En la mayoría de los casos, no importa, pero es un buen hábito para hacerlo de todos modos, porque en ocasiones es posible que desee verificar si una lista de cosas no comparables está vacía. Aquí hay un ejemplo corto y claro que muestra esta diferencia:

> null [id] False > [id] == [] <interactive>:1:1: error: • No instance for (Eq (a0 -> a0)) arising from a use of ‘==’ (maybe you haven''t applied a function to enough arguments?) • In the expression: [id] == [] In an equation for ‘it’: it = [id] == []