2010-10-01 10 views
6

Mi función es el siguiente:¿existe alguna forma de escribir la función menos (eliminar elementos de una lista)?

minus :: (Eq a) => [a] -> [a] -> [a] 
minus [] xs      = [] 
minus (y:ys) xs | y `notElem` xs = y : (minus ys xs) 
       | otherwise  = minus ys xs 

Se puede utilizar la siguiente manera:

[99,44,55,22,23423] `minus` [55,22] 

con la salida: [99,44,23423]

escribí esto porque estoy mirando problema Proyecto Euler 7 , y el Tamiz de Eratóstenes parece ser la herramienta correcta, y lo fue, pero seguí leyendo el Wikipedia page y llegué a la parte sobre el tamiz de Euler.

Intenté copiar/pegar el código y ejecutarlo en GHCi, pero mi versión de GHCi no tiene un módulo llamado Data.OrdList, y no pude encontrar una función llamada minus en Hoogle.

Este es el código de Wikipedia:

import Data.OrdList (minus) 

primes = euler [2..] 
euler (p : xs) = p : euler (xs `minus` map (*p) (p : xs)) 

Si sustituyo mi función menos allí, me sale un error de falta de memoria, porque mi función no es perezoso.

¿Hay alguna manera de hacer una función de menos perezoso?

¿Mi función menos hace lo mismo que la función menos en el artículo de Wikipedia?

+0

Así como una nota: http://hackage.haskell.org/package/primes contiene un tamiz perezoso muy eficiente de Eratóstenes, basado en colas de prioridad y enmascaramiento de muchos no obvia -primas de la lista que se busca. – Carl

+0

Sugeriría una versión más simple y más fácil de leer de su código (no para responder a la pregunta, solo para darle una idea a alguien): '' ls1 'minus' ls2 = [x | x <- ls1, x 'notElem' ls2]' ' – nfs

Respuesta

6

Como sepp2k señaló, la implementación de minus debe asumir listas ordenadas. Aquí hay una posible implementación:

minus :: Ord a => [a] -> [a] -> [a] 
minus [] _ = [] 
minus xs [] = xs 
minus [email protected](x:xs) [email protected](y:ys) 
    | x > y = minus l1 ys 
    | x < y = x : minus xs l2 
    | otherwise = minus xs l2 
+0

tu código llegó primero, ¡así que te recojo! Claramente necesito aprender más sobre la pereza en Haskell. –

+1

Un lema no oficial de Haskell es "Evitar el éxito a toda costa". Creo que la pereza es lo que mantiene el lenguaje alejado de las masas. La pereza es difícil, incluso más difícil que las mónadas. No es explícito en el idioma, tienes que analizar todo. En algún momento, quiere la pereza (como en esta publicación), pero cuando optimiza su código, es posible que desee rigor. No tengo suficiente experiencia con Haskell para estar seguro de que las dificultades relacionadas con la pereza/rigor desaparecerán con suficiente práctica. – gawi

5

¿Hay alguna manera de hacer una función menos activa?

Si no asume que las listas de entrada están ordenadas (y no tiene permiso para ordenarlas), no las hay. Tendrá que saber si el primer elemento de list1 está en list2 antes de saber cuál será el primer elemento del resultado. Por lo tanto, no puede evitar tener que evaluar toda la segunda lista antes de producir un solo elemento en el peor de los casos.

Sin embargo, si asume que las listas de entrada están ordenadas (que el menos utilizado por wikipedia claramente hace ya que el módulo se llama * Ord * List), es muy fácil escribir una función menos que sea floja.

Y dado que su lista de entrada en realidad está ordenada, dicha función menos funcionaría perfectamente para sus necesidades.

3

Google superó a Hoogle.

Tomado de http://hackage.haskell.org/packages/archive/data-ordlist/0.0.1/doc/html/src/Data-OrdList.html

minus :: (Ord a) => [a] -> [a] -> [a] 
minus = minusBy compare 

minusBy :: (a -> a -> Ordering) -> [a] -> [a] -> [a] 
minusBy cmp = loop 
    where 
    loop [] _ys = [] 
    loop xs [] = xs 
    loop (x:xs) (y:ys) 
     = case cmp x y of 
      LT -> x : loop xs (y:ys) 
      EQ ->  loop xs ys 
      GT ->  loop (x:xs) ys 
+0

¡Gracias! Ojalá hubiera pensado en Google para Data.OrdList –

Cuestiones relacionadas