studio - Haskell: escribe en mayúsculas todas las letras en una lista[String] con toUpper
string en haskell (3)
Sé que toUpper en esta línea de código obtiene una lista como valor y, por lo tanto, no puede funcionar, pero sabe cómo bajar un nivel en la lista y aplicar el mapa a Superior.
Use (map . map)
lugar de map
.
nb (map . map) toUpper
es lo mismo que map (map toUpper)
como lo sugieren las otras respuestas. Lo menciono porque, personalmente, me parece más claro: parece que va a bajar dos niveles para aplicar a toUpper
. (Puede que no esté familiarizado con el operador de composición de funciones (.)
, Búsquelo o pregúntele si es necesario).
Otras funciones con un tipo similar ( (a -> b) -> something a -> something b
), como fmap
, Data.Map.map
, first
y second
, se pueden combinar entre sí y con el map
de forma similar .
Tal vez no encuentre (map . map) toUpper
más claro que el map (map toUpper)
; lo suficientemente justo.
Tengo una lista [String] la tarea para eliminar esos elementos en la lista, que tienen "q" o "p" y luego escribe en mayúscula todas las letras de la lista con toUpper.
Lo que intenté todavía es como sigue:
delAndUpper :: [String] -> [String]
delAndUpper myList = filter (/x -> not(''p'' `elem` x || ''q'' `elem` x)) myList
Elimina los elementos no deseados de la lista correctamente, sin embargo, no puedo aplicar a Upper en esta lista, ya que el tipo de toUpper es Char.
Lo intenté con el mapa y no funciona.
delAndUpper myList = map toUpper (filter (/x -> not(''p'' `elem` x || ''q'' `elem` x)) myList)
Sé que toUpper en esta línea de código obtiene una lista como valor y, por lo tanto, no puede funcionar, pero sabe cómo bajar un nivel en la lista y aplicar el mapa a Superior.
Me podría ayudar.
¡Gracias por adelantado!
Saludos
Ya casi estás allí, solo necesitas un segundo map
.
map (map toUpper) (filter (/x -> not(''p'' `elem` x || ''q'' `elem` x)) myList)
Esto es porque String
es completamente sinónimo de [Char]
en vainilla haskell. Dado que el tipo de mapa es
(a->b) -> [a] -> b
y tenemos
toUpper :: Char -> Char
String :: [Char]
Devolveremos otra String
, excepto en mayúscula.
Por cierto, ese filtro feo-ish se puede reemplazar haciendo más bonito haciendo que use flechas :) (Piense en esto como funciones más estructuradas)
map (map toUpper) . filter $ elem ''p'' &&& elem ''q'' >>> arr (not . uncurry (||))
Gratuidad? Tal vez, pero un poco genial.
Mapeo de un nivel más profundo
Necesitas usar el map (map toUpper)
.
Esto se debe a que tiene [String]
lugar de String
.
toUpper :: Char -> Char
map toUpper :: [Char] -> [Char]
es decir
map toUpper :: String -> String
map (map toUpper) :: [String] -> [String]
map toUpper
mayúscula una Cadena, haciendo que cada letra en mayúscula, por lo que el map (map toUpper)
capitaliza cada Cadena en una lista de Cadenas.
Tu función se vuelve
delAndUpper myList = map (map toUpper) (filter (/x -> not(''p'' `elem` x || ''q'' `elem` x)) myList)
dave4420 hizo una buena sugerencia de que (map.map) toUpper
es una manera ordenada de escribir un map (map toUpper)
que te ayuda a pensar en dos niveles de lista de forma bastante simple y natural: echa un vistazo a su respuesta también.
¿Podemos desconectar la p y la q?
Preguntó si había una forma más corta de escribir la condición, y no le gustó la codificación dura de `q`
`p`
. Estoy de acuerdo en que esos bits de `elem`
no son bonitos. Pasemos en la lista de letras no permitidas y arreglemos un poco:
delAndUpper omit strings = map (map toUpper) (filter ok strings) where
ok xs = not (any (`elem` omit) xs)
Aquí (`elem` omit)
comprueba si un personaje está en la lista de los que nos haría omitir la palabra, entonces (any (`elem` omit) xs)
verifica si alguno de los caracteres de xs
está prohibido. Por supuesto, si ninguno está prohibido, está ok
.
Su original delAndUpper
ahora sería delAndUpper "pq"
, o si también desea rechazar el capital P y Q, delAndUpper "pqPQ"
. (Más sobre esto más adelante).
¿Podemos hacerlo más conciso?
Veamos si no podemos escribir ok
un poco más corto. Lo primero que pensé fue utilizar pointfree
en él (ver mi respuesta a otra pregunta para obtener detalles sobre cómo ejecutarlo en ghci), pero pareció colgarse, así que al usar algunos trucos de transformación estándar, podemos componer not
con una función que tome dos argumentos antes de darnos un Bool haciendo (not.).f
lugar de not.f
como lo haríamos con una función que acaba de darnos un Bool después de la primera entrada. any
está tomando (`elem` omit)
como su primer argumento. Esto nos da
ok xs = ((not.).any) (`elem` omit) xs
de donde podemos eliminar los xs finales:
ok = ((not.).any) (`elem` omit)
y en línea:
delAndUpper omit strings = map (map toUpper) (filter (((not.).any) (`elem` omit)) strings)
Tampoco estoy interesado en las strings
finales:
delAndUpper omit = map (map toUpper).filter (((not.).any) (`elem` omit))
(Podríamos deshacernos del argumento omit
también e ir completamente sin puntos, pero eso sería demasiado lento en el camino difícil de leer para mi gusto).
¿Hacia dónde Q?
> delAndUpper "pq" $ words "The Queen has probably never had a parking ticket."
["THE","QUEEN","HAS","NEVER","HAD","A","TICKET."]
¿Es este el comportamiento requerido? Parece extraño excluir cuidadosamente las variantes en minúsculas y luego hacer todo en mayúsculas. Podríamos hacerlo al revés:
upperAndDel omit = filter (((not.).any) (`elem` omit)).map (map toUpper)
dando
> upperAndDel "PQ" $ words "The Queen has probably never had a parking ticket."
["THE","HAS","NEVER","HAD","A","TICKET."]