es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Producto cartesiano en Haskell, Monad con filtro.

Esto tiene que ser muy sencillo y estoy insatisfecho de no poder resolverlo en este punto de mi experiencia en Haskell. Quiero obtener el producto cartesiano de una lista consigo misma, pero quiero filtrar los elementos idénticos. No quiero un filtro posterior.

Esto me da el producto cartesiano, aparentemente configurado para simplemente agregar un filtro…

p as bs = do
            a <- as
            b <- bs
            return (a,b)

p [1,2,3] [1,2,3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]

He leído que return () es básicamente un no-op dentro de la notación do, pero esto no compila. (¿Se están mezclando las tuplas?)

pf as bs = do
            a <- as
            b <- bs
            if a == b then return () else return (a,b)

Couldn’t match type () with `(a, a)’
Expected type: [(a, a)]
Actual type: [()]

He intentado algunas otras cosas, como la función if' del wiki de Haskell. También intenté when sin éxito. Cuando el filtro es when,

when (a /= b) return (a,b)

Couldn’t match type m0 (a, a)' with()’
Expected type: (a, a) -> ()
Actual type: (a, a) -> m0 (a, a)

Supongo que estos mensajes de error me están señalando el problema, pero aún no soy hábil para traducir la mayoría de ellos.

Tal vez haya una función de nivel superior que pueda ocuparse de esto de una manera más directa (¿filterM?), y estaré encantado de conocer su uso, pero aún así quiero saber cómo resolver este problema en la función pf anterior.

Gracias

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para obtener el producto cartesiano de una lista con sí misma, filtrando los elementos idénticos, puedes modificar la función original p de la siguiente manera:

    p as bs = do
                a <- as
                b <- bs
                if a == b then return [] else return [(a,b)]
    
    pf as bs = concat $ p as bs
    

    La función concat se utiliza para aplanar la lista de tuplas en una única lista. El return [] se utiliza para evitar devolver tuplas con elementos idénticos.

    Alternativamente, puedes utilizar la función filter en el producto cartesiano para eliminar los elementos idénticos:

    p as bs = [(a,b) | a <- as, b <- bs]
    pf as bs = filter (\(a, b) -> a /= b) $ p as bs
    

    El \ se utiliza para definir una función lambda que filtra las tuplas con elementos idénticos.

Comments are closed.