How to convert a String to lowercase using lambda expressions - haskell

I want to know how to convert a string to lowercase using the ToLower function (Char -> Char).
This is the code I have so far:
let newlist = (\(h:t) -> c (h) ++ newlist (\c -> toLower c)
I can't see how to do it without using recursion, which I don't know how to use in a lambda expression

It would be easier to not use a lambda expression considering you can eta-reduce to not explicitly name the variable your function accepts. For example you could use a list comprehension:
import Data.Char
lowerString str = [ toLower loweredString | loweredString <- str]
Which you would call as:
ghci> lowerString "Hello"
hello
Alternatively, you could use map:
lowerString = map toLower
If you insist on using a lambda expression, it would look something like this:
import Data.Char
lowerString = \x -> map toLower x
Which again, is not as nice.

With a lambda expression you'd still need to recursively check each character of the string, or you could use map which is still a recursive function that applies the function (a -> b) to every element in the list, for example:
newList [] = []
newList xs = (\(y:ys) -> if x `elem` ['A'..'Z'] then toLower y : newList ys else y : newList ys) xs
With map is actually much simpler due to reasons explained in the first paragraph, check mnoronha's answer as he already gave you the answer, but that's if you're thinking of using map in conjunction with toLower.
This is an example without a lambda expression, which requires you to import 2 functions from Data.Char, recursively check the rest of the string and replace each character with its lower case version.
newList :: String -> String
newList [] = []
newList (x:xs) = if x `elem` ['A'..'Z']
then chr (ord x + 32) : newList xs
else x : newList xs
or with guards
newList :: String -> String
newList [] = []
newList (x:xs)
| x `elem` ['A'..'Z'] = chr (ord x + 32) : newList xs
| otherwise = x : newList xs

This may be more trouble than it's worth but you can use the fix function to recursively call a lambda function.
fix :: (a -> a) -> a
fix f = let x = f x in x
The following code uses the same method used on this page : https://www.vex.net/~trebla/haskell/fix.xhtml to transition from a non-lambda version to a lambda version to (eventually) using fix to recursively call a lambda function without introducing a new variable
import Data.Char (toLower)
import Control.Monad.Fix (fix)
main :: IO ()
main = do
-- calling non lambda version
let newlist1 s = if null s then [] else toLower (head s) : newlist1 (tail s)
print $ newlist1 "Hello"
-- calling lambda version
let newlist2 = \s -> if null s then [] else toLower (head s) : newlist2 (tail s)
print $ newlist2 "Hello"
-- defining lambda version locally
-- ( at this point the scope of newlist3 is local to the let statement )
print $ (let newlist3 = \s -> if null s then [] else toLower (head s) : newlist3 (tail s) in newlist3 ) "Hello"
-- making function an argument to be called recursively
print $ (let newlist3 = (\v -> \s -> if null s then [] else toLower (head s) : v (tail s)) newlist3 in newlist3 ) "Hello"
-- isolating function to be "fixed".
let f = (\v -> \s -> if null s then [] else toLower (head s) : v (tail s))
print $ (let newlist3 = f newlist3 in newlist3 ) "Hello"
-- using fix = let x = f x in x
print $ (fix f) "Hello"
-- f2 is slightly simpler version of f
let f2 = (\v s -> if null s then [] else toLower (head s) : v (tail s))
print $ (fix f2) "Hello"
-- inlining f2 to get recursive call to lambda
print $ (fix (\v s -> if null s then [] else toLower (head s) : v (tail s))) "Hello"

Related

String to List of Int

I would like to incorporate Maybe [int] into this.
The code should take a string and filter out spaces turning it into a list of integers and if their are letters return Nothing.
text2digits :: String -> [Int]
text2digits s = case s of
[] -> []
x:xs
|isDigit x -> digitToInt x :text2digits (filter (/= ' ') xs)
|otherwise -> undefined
input "1233 5687" output: [1,2,3,3,5,6,8,7]
input "a89" required output : Nothing
current output: undefined
I have tried this but it shows up a list of errors
text2digits :: String -> Maybe [Int]
text2digits s = case s of
[] -> Just []
x:xs
|isDigit x -> Just digitToInt x :text2digits (filter (/= ' ') xs)
|otherwise -> Nothing
What is wrong with the code, that you've specified for text2digits :: String -> Maybe [Int]?
The problem is in this line:
digitToInt x :text2digits (filter (/= ' ') xs)
text2digits returns value of Maybe [Int] type, but (:) expects it to be [Int].
In order to fix it, you can use fmap or <$> to apply a function to a structure inside the functor Maybe:
import Data.Char
text2digits :: String -> Maybe [Int]
text2digits s = case s of
[] -> Just []
x:xs
|isDigit x -> ((digitToInt x) :) <$> text2digits (filter (/= ' ') xs)
|otherwise -> Nothing
main = print $ text2digits "1233 5687"
Or probably you can use traverse to refactor the function a bit:
import Data.Char
text2digits :: String -> Maybe [Int]
text2digits s =
traverse digitToMaybeInt $ filter (/= ' ') s
where
digitToMaybeInt x
| isDigit x = Just $ digitToInt x
| otherwise = Nothing
main = print $ text2digits "89"

Haskell: Efficient accumulator

What is the best way to map across a list, using the result of each map as you go along, when your result is of a different type to the list.
for example
f :: Int -> Int -> String -> String
l = [1,2,3,4]
I would like to have something that walks along the list l and does:
f 1 2 [] = result1 => f 2 3 result1 = result2 => f 3 4 result3 ==> return result3.
I can sort of get this to work with a an accumulator, but it seems rather cumbersome. Is there a standard way to do this... or is this something for Monads??
Thanks!
NB the function above is just for illustration.
This is just a fold left over the pairs in the input list:
f :: Int -> Int -> String -> String
f = undefined
accum :: [Int] -> String
accum xs = foldl (flip . uncurry $ f) "" $ zip xs (drop 1 xs)
You probably want to use Data.List.foldl' instead of foldl, but this is an answer that works with just Prelude.
Seems like a job for fold:
func f l = foldl (\s (x, y) -> f x y s) "" (zip l (tail l))
-- just some placeholder function
f :: Int -> Int -> String -> String
f x y s = s ++ " " ++ show(x) ++ " " ++ show(y)
l = [1,2,3,4]
main = print $ func f l
prints:
" 1 2 2 3 3 4"
(if you can change the signature of f, you can get rid of the ugly lambda that rearranges arguments)
Of course, rather than zipping, you could pass along the previous element inside the fold's accumulator. For example:
l = [1,2,3,4]
f x y = (x,y)
g b#(accum,prev) a = (accum ++ [f prev a],a)
main = print (foldl g ([],head l) (tail l))
Output:
([(1,2),(2,3),(3,4)],4)

While loop in Haskell

I want to create a while loop to concatenate strings in the xs list
until I find an empty string, but it seems neither we have a chance to
increment an Int nor create a while loop.
So this looks like a pseudo code for Haskell, but how can I actually implement my solution?
prt :: String -> [String] -> Int -> String
prt str xs x = do
while((xs !! (x)) /= "")
str = str ++ (xs !! (x++))
Forget array indexes: they are often not needed. All you have to do for your task is getting the longest prefix of your list containing only non-empty strings.
takeWhile (not . null) xs
-- or
takeWhile (/= "") xs
Then you want to concatenate these strings.
concat $ takeWhile (/= "") xs
If you want to start after n strings for some reason, just drop the first n before beginning:
concat $ takeWhile (/= "") $ drop n xs
If you really want to do a custom "loop", use recursion:
g xs n = f $ drop n xs
f [] = ""
f ("":xs) = ""
f (x:xs) = x ++ f xs

Filter by length

How I can make here filter (x:xs) = (x, length (x:xs)) that puts length when length > 1?
Currently, if input is abcaaabbb output is [('a',1),('b',1),('c',1),('a',3),('b',3)], but I'm looking for abca3b3.
My code:
import Data.List
encode :: [Char] -> [(Char, Int)]
encode s = map go (group s)
where go (x:xs) = (x, length (x:xs))
main = do
s <- getLine
print (encode s)
Last string will be putStrLn (concat (map (\(x,y) -> x : [y]) (encode s))) for convert list to string.
As I am a newbie myself, this is probably not very haskellian. But you can do it about like this (xs as would be the list [('a', 1), ('b', 2), ('a', 3)]):
Create "a1b2a3":
concat $ map (\(c, l) -> c:(show l)) xs
Filter out 1s:
filter (\x -> x /= '1') "a1b2a3"
will give you "ab2a3"
You can't have a list like this in Haskell:
[('a'),('b'),('c'),('a',3),('b',3)]
Each element if a list needs to have the same type in haskell, and ('c') [('a') :: Char] and ('b',3) [('a',1) :: Num t => (Char, t)] are different types.
Maybe also have a look at List of different types?
I would suggest, that you change your list to a (Char, Maybe num) datastructure.
Edit:
From your new question, I think you have been searching for this:
import Data.List
encode :: [Char] -> [(Char, Int)]
encode s = map go (group s)
where go (x:xs) = (x, length (x:xs))
f :: (Char, Int) -> String
f (a, b) = if b == 1 then [a] else [a] ++ show b
encode2 :: [(Char, Int)] -> String
encode2 [] = []
encode2 (x:xs) = f(x) ++ encode2 xs
main = do
s <- getLine
putStrLn $ encode2 $ encode s
Not sure if this suits your needs, but if you do not need filtering, this does the work:
encode::String -> String
encode "" = ""
encode (x:xs) = doIt0 xs x 1 where
doIt0 [] ch currentPos = [ch]++showPos currentPos
doIt0 (x:xs) ch currentPos
|x==ch = doIt0 xs ch $ currentPos+1
|otherwise= [ch]++ (showPos currentPos) ++ (doIt0 xs x 1)
showPos pos = if pos> 1 then show pos else ""
main = do
s <- getLine
print (encode s)

Haskell filter string with only the first occuring Char

I want to filter a string with a string.
What I want is to use delete every first occurring char.
myFunc :: String -> String -> String
Like:
myFunc "dddog" "bigdddddog" = "biddg"
In "dddog": 3x d, 1x o, 1x g
In the second string it removed 3x d, 1x o and 1x g
So the output: biddg
I can't use filter for it, because it will delete all occurring chars.
And I struggled a long time with it.
Thanks in advance:)
How about
Prelude> :m +Data.List
Prelude Data.List> "bigdddddog" \\ "dddog"
"biddg"
Not the nicest solution, but you can understand easier what's going on:
myfunc :: String -> String -> String
myfunc [] xs = xs
myfunc (x:xs) ys = myfunc xs $ remove x ys
where
remove _ [] = []
remove x (y:ys) = if x == y then ys else y : remove x ys
As you commented, you want to use guards. Do you mean this?
myfunc :: String -> String -> String
myfunc [] xs = xs
myfunc (x:xs) ys = myfunc xs $ remove x ys
remove :: Char -> String -> String
remove _ [] = []
remove x (y:ys)
| x == y = ys
| otherwise = y : remove x ys
some of the other solutions don't seem to produce the same result you posted. I think I have a simple solution that does what you asked for but I may be misunderstanding what you want. All I do in the following code is go though the list and apply 'delete' to every element in the list. It's not exactly efficient but it gets the job done.
import Data.List
myFunc (x:xs) ys = myFunc xs (delete x ys)
myFunc [] ys = ys
There are perhaps more efficient solutions like storing the "to remove" list in a tree with the number of occurences stored as the value then traversing the main list testing to see if the count at that key was still greater than zero. I think that would give you O(n*lg(m)) (where n is the size of the list to be removed from and m is the size of the "to remove" list) rather than O(n*m) as is the case above. This version could also be maid to be lazy I think.
edit:
Here is the tree version I was talking abut using Data.Map. It's a bit complex but should be more efficient for large lists and it is somewhat lazy
myFunc l ys = myFunc' (makeCount l) ys
where makeCount xs = foldr increment (Map.fromList []) xs
increment x a = Map.insertWith (+) x 1 a
decrement x a = Map.insertWith (flip (-)) x 1 a
getCount x a = case Map.lookup x a of
Just c -> c
Nothing -> 0
myFunc' counts (x:xs) = if (getCount x counts) > 0
then myFunc' (decrement x counts) xs
else x : myFunc' counts xs
myFunc' _ [] = []
I am not quite sure about how you want your function to behave, how about this?
import Data.List (isPrefixOf)
myFunc :: String -> String -> String
myFunc _ [] = []
myFunc y x'#(x:xs) | y `isPrefixOf` x' = drop (length y) x'
| otherwise = x : myFilter xs y
This gives the following output in GHCi:
> myFunc "dddog" "bigdddddog"
> "bigdd"
If this is not what you had in mind, please give another input/output example.
I like kaan's elegant solution. In case you meant this...here's one where the "ddd" would only be removed if matched as a whole:
import Data.List (group,isPrefixOf,delete)
f needles str = g (group needles) str where
g needles [] = []
g needles xxs#(x:xs)
| null needle' = [x] ++ g needles xs
| otherwise = let needle = head needle'
in g (delete needle needles) (drop (length needle) xxs)
where needle' = dropWhile (not . flip isPrefixOf xxs) needles
Output:
*Main> f "dddog" "bigdddddog"
"biddg"
*Main> f "dddog" "bdigdogd"
"bdidgd"
No monadic solution yet, there you go:
import Control.Monad.State
myFunc :: String -> State String String
myFunc [] = return ""
myFunc (x:xs) = get >>= f where
f [] = return (x:xs)
f (y:ys) = if y == x then put ys >> myFunc xs
else myFunc xs >>= return . (x:)
main = do
let (a,b) = runState (myFunc "bigdddddog") "dddog" in
putStr a
Using predefined functions from Data.List,
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
-- lookup :: (Eq a) => a -> [(a, b)] -> Maybe b
{-# LANGUAGE PatternGuards #-}
import Data.List
picks [] = [] -- http://stackoverflow.com/a/9889702/849891
picks (x:xs) = (x,xs) : [ (y,x:ys) | (y,ys) <- picks xs]
myFunc a b = concat . snd $ mapAccumL f (picks a) b
where
f acc x | Just r <- lookup x acc = (picks r,[])
f acc x = (acc,[x])
Testing:
Prelude Data.List> myFunc "dddog" "bigdddddog"
"biddg"
edit: this is of course a bit more complex than (\\). I'll let it stand as an illustration. There could be some merit to it still, as it doesn't copy the 2nd (longer?) string over and over, for each non-matching character from the 1st (shorter) string, as delete apparently does, used in (\\) = foldl (flip delete).

Resources