Hogyan lehetne javítani ezt a feladatot haskellben?
Működik az összes tesztesetre kivéve az utolsóra.Valaki tudna segíteni mivel tudnám javítani a kódót vagy más megoldást találni?
Definiáld azt a függvényt, amely egy szöveget normalizál a következőképpen: az angol ábécé kisbetűit nagybeűkké alakítja,az angol ábécé nagybetűit változatlanul hagyja, és minden egyéb karaktert (írásjeleket, whitespace-eket, stb.) eltávolít a szövegből.
A megvalósításhoz használjuk a map és filter függvényeket!
import Data.Char as Char
normalizeText :: String -> String
normalizeText = map Char.toUpper . filter Char.isLetter
-- Az alábbi tesztesetek közül mindegyiknek True-t kell adnia:
-- normalizeText "sos" == "SOS"
-- normalizeText ".! 7" == ""
-- normalizeText "Save our souls!" == "SAVEOURSOULS"
-- normalizeText "limonádé" == "LIMOND"
Vicces, de létezik rá egysoros is:
import Data.Char
"majom csapat" >>= (filter isAlpha . return . toUpper)
ebből lesz "MAJOMCSAPAT"
Persze ez kis kitérő, inkább a monászok témakörébe tartozik, és majd a list mint monász témájába tartozik.
Az eredeti feladat szelleméhez illő megoldás:
mapMaybe (filterMaybe isAlpha . toUpper) "majom csapat"
ahol a filterMaybe segédfüggvényt az alábbiként kell definialni:
filterMaybe :: (a -> Bool) -> Maybe a
filterMaybe property a = if property a then Just a else Nothing
Egyébként létezik filterMaybe függvény, de nem a standard könyvtárban, hanem csak ritkább, kevésbé ismert csomagok részeként:
Bocsánat, persze a filterMaybe segédfüggvény típusát elgépeltem:
filterMaybe :: (a -> Bool) -> a -> Maybe a
filterMaybe property a = if property a then Just a else Nothing
(Szererncsére a Hoogle-ban helyesen kerestem rá)
Megoldás listaabsztrakcióval:
[toUpper a | a <- "majom csapat", isAlpha a && isUpper a]
Megoldás a lista mint monász do-jelölésével:
do
a <- "limonádé ízű"
if isAscii a && isLetter a then return (toUpper a) else ""
vagy a whitespace tagolást nem használva:
do {a <- "limonádé ízű"; if isAscii a && isLetter a then return (toUpper a) else "";}
Elvileg ha már a lista mint monász do-jelölésének fogalmára hegyezzük ki a dolgot, akkor így lenne szép:
import Control.Monad
do
a <- "limonádé ízű"
if isAscii a && isLetter a then return (toUpper a) else mzero
De persze elég a kitérőből, a lényeg még az, hogy az isAscii vagy az isLetter önmagában nem elég, erre jó tesztpróba: "LIMONÁDÉ ÍZÚ". Az isAscii bennehagyja a szóközt "LIMOND Z".
Az \a -> isAscii a && isLetter a féle konjunkció együtt már a helyes "LIMONDZ" választ adja.
Összesítve, lehetne egy validSymbol függvényt írni:
isValidSymbol :: Char -> Bool
isValidSymbol c = isAscii c && isLetter c
és emellé még az elébb említett filterMaybe függvényt:
filterMaybe :: (a -> Bool) -> a -> Maybe a
filterMaybe property a = if property a then Just a else Nothing
és akkor ebből
mapMaybe (filterMaybe isValidSymbol . toUpper) "majom csapat"
A másik megoldás esetén kimaradhat a filterMaybe segédfüggvény:
lista mint monász:
"limonádé ízű" >>= (filter isValidSymbol . return . toUpper)
Létezik igazi egysoros is, amely -- ha az import-októl eltekintünk -- tényleg egysoros, úgy, hogy még lambdákat sem használ:
import Data.Char (isLetter, isAscii)
import Control.Monad (liftM2)
"limonádé ízű" >>= filter (liftM2 (&&) isAscii isLetter) . return . toUpper
Ez igazából nem nagy változás, annyi csak a lényeg, hogy az isAscii és az isLetter mint tulajdonság közvetlenül is összeÉSelhető: listM2 (&&) isAscii isLetter. Vagyis az ÉS mint logikai kapcsolat ,,felemelhető'' a Bool szintjáről a Bool-> Char ,,tulajdonságszintre''. Ez persze lambdával is megoldható: \a -> isAscii a && isLetter a.
isValidSymbol = liftM2 (&&) isAscii isLetter
szóval a megtakarítás nem nagy a hagyományos
isValidSymbol c = isAcii c && isLetter c
definícióhoz képest, viszont egysorosba könnyebb közvetlenül beágyazni.
Szóval ez inkább csak érdekesség, mögötte az áll, hogy az adott értelmezési tartományból kiinduló függvények maguk is egy speciális monászt alkotnak, ezért minden, az értékkészletükre vonatkozó művelet ,,felemelhető'' a szintjükre:
Kihagyom a feladathoz nem illő kanyarokat:
import Data.Char (toUpper, isAscii, isLetter)
normalizeText :: String -> String
bormalizetext = filter (\c -> isLetter c && isAscii c) . map toUpper
Ez írható át lambdák nélkül úgy, ha valaki szereti a „point-free” stílust:
import Data.Char (toUpper, isAscii, isLetter)
import Control.Monad (liftM2)
normalizeText :: String -> String
normalizetext = filter (liftM2 (&&) isLetter isAscii) . map toUpper
Kapcsolódó kérdések:
Minden jog fenntartva © 2025, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!