Can someone explain this line of code in Haskell - haskell

So i have this program, it finds lowercase letters and turns them to uppercase. It works but can someone just explain what the code after the else statement does.
raise :: String -> String
raise xs =
[x | char <- xs
, char `elem` (['a'..'z'] ++ ['A'..'Z'] ++ ['0' .. '9'])
, let x = if char `elem` ['A'..'Z'] ++ ['0' .. '9']
then char
else ['A'..'Z'] !! head [i | (i, x) <- zip [0..] ['a'..'z']
, x == char]]

you can try it yourself in ghci (type 'ghci' or 'stack ghci' from a command line, depending on how you've installed Haskell, or even use one of those 'try haskell online' services)!
> let f char = ['A'..'Z'] !! head [i | (i, x) <- zip [0..] ['a'..'z'], x == char]
> f 'x'
'X'
> f '3'
{Prelude.head empty list error}
What does the part in the list do? Let's try it out!
> let f char = [i | (i, x) <- zip [0..] ['a'..'z'], x == char]
> f 'b'
[2]
> f '3'
[]
See how you can use ghci to figure out what a function does?
Need help figuring out what arguments to add to f? Consider this:
> let f = [i | (i, x) <- zip [0..] ['a'..'z'], x == char]
{not in scope error: char}

Related

Haskell, how to return a list without encountering an error

So I'm trying to wrap my head around Haskell with my first project where i have a function encountering an error:
Exception: prelude.head: empty list.
selectNextGuess :: [[Card]] -> [Card]
selectNextGuess lst
| length lst >= 1250 = lst !! (div (length lst) 2)
| otherwise = newGuess
where fbList = [[feedback x y | x <- lst, y <- lst]]
valuesList = [(calcValues(group $ sort[feedback y x | y <- lst, y /= x]), x) | x <- lst]
(_, newGuess) = head(sort valuesList)
Any advice in steering me in the right direction to solve this would be greatly appreciated.
Cheers
TL;DR: since a list can be empty, and there is no minimal element in the empty list, the way to return a list without the error is to maybe return a list, or rather to return a Maybe list.
If you call selectNextGuess [], lst inside the function selectNextGuess becomes []. Then, valuesList = [(calcValues(group $ sort[feedback y x | y <- lst, y /= x]), x) | x <- [] ] = [] is also an empty list. And then (_, newGuess) = head (sort valuesList) = head (sort []) = head [] is called.
But there is no head element in the empty list. This is what the error message is telling us. You called head with [], which is forbidden, because it has no answer.
The usual solution is to make this possibility explicit in the data type. We either have just one answer, for a non-empty list, or we have nothing:
data Maybe a = Just a | Nothing
is such built-in type. So we can use it, and handle the empty lst explicitly:
selectNextGuess :: [[Card]] -> Maybe [Card]
selectNextGuess lst
| length lst >= 1250 = Just $ lst !! (div (length lst) 2)
| null lst = Nothing
| otherwise = Just newGuess
where fbList = [[feedback x y | x <- lst, y <- lst]]
valuesList = [(calcValues(group $ sort[feedback y x | y <- lst, y /= x]), x)
| x <- lst]
(_, newGuess) = head (sort valuesList)
Using null as a guard like that is a bit of an anti-pattern. We usually achieve the same goal with the explicit pattern in a separate clause, like
selectNextGuess :: [[Card]] -> Maybe [Card]
selectNextGuess [] = Nothing
selectNextGuess lst
| length lst >= 1250 = Just $ lst !! (div (length lst) 2)
| otherwise = Just newGuess
where ......
Using that head ... sort ... combination to find the minimal element is perfectly fine. Due to Haskell's lazy evaluation and the library sort being implemented as bottom-up mergesort, it will take O(n) time.
There is also a shorter way to write down the same thing,
....
| otherwise = listToMaybe . map snd $ sort valuesList -- or,
= listToMaybe [ x | (_, x) <- sort valuesList ] -- whichever you prefer.
where fbList = .....
valuesList = .....
Since there is no more than one value "inside" a Maybe _, the conversion function listToMaybe already takes just head element, implicitly.
Moreover, it produces Nothing automatically in the empty list [] case. So the explicit pattern clause can be removed, this way.

Haskell percentage of char in a string

I am trying to make a program that receives a STRING and returns the percentage of 'C' and 'A' in it. However it is going to me wrong, this is my code:
function' :: [Char] -> Double
function' xs = 100* ( fromIntegral final0 )
where final0 = length $ filter (\x-> x == 'C'|| x == 'G') xs
if I run: function '$ replicate 20' C ', return me 2000.0 and should give me 1.0
Some errors in the question
You said
'C' and 'A'
While your code says
\x-> x == 'C'|| x == 'G'
What you're doing
You're measuring the number of Cs and Gs, and *100, and return the result.
How to solve
do not *100, do / length xs.
Solution
function' xs = fromIntegral final0 / fromIntegral final1
where final0 = length $ filter (\x-> x == 'C'|| x == 'G') xs
final1 = length xs

Haskell - how to generate permutations

How can I create a function which lazily makes permutations for the chars '_' and '*' like this:
For example:
Main> function 3
["___","*__","_*_","__*","**_","_**","*_*","***"]
First element is made only from _, the next 3 are permutations that lists: *__, the second 3 are permutations that lists **_, and the last element contains only *.
How can I do that?
Here's another "correct order" version:
function :: Int -> [String]
function c = concatMap helper $ zip (reverse [0..c]) [0..c]
helper :: (Int, Int) -> [String]
helper (c, 0) = [replicate c '_']
helper (0, c) = [replicate c '*']
helper (cUnderscores, cAsterisks) = map ('_' :) (helper (cUnderscores - 1, cAsterisks))
++ map ('*' :) (helper (cUnderscores, cAsterisks - 1))
You might want to look at replicateM.
let k = ["_", "*"]
let p = [ a ++ b ++ c | a <- k, b <- k, c <- k ]
The “correct order” version:
import Data.List
function k = concatMap (nub . permutations . pat) [0..k]
where pat x = replicate x '*' ++ replicate (k-x) '_'
I don’t know how to step from one permutation to another in constant time, though.

FizzBuzz cleanup

I'm still learning Haskell, and I was wondering if there is a less verbose way to express the below statement using 1 line of code:
map (\x -> (x, (if mod x 3 == 0 then "fizz" else "") ++
if mod x 5 == 0 then "buzz" else "")) [1..100]
Produces:
[(1,""),(2,""),(3,"fizz"),(4,""),(5,"buzz"),(6,"fizz"),(7,""),(8,""),(9,"fizz"),(10,"buzz"),(11,""),(12,"fizz"),(13,""),(14,""),(15,"fizzbuzz"),(16,""),(17,""),(18,"fizz"),(19,""),(20,"buzz"),(21,"fizz"),(22,""),(23,""),(24,"fizz"),(25,"buzz"),(26,""),(27,"fizz"),(28,""),(29,""),(30,"fizzbuzz"), etc
It just feels like I'm fighting the syntax more than I should. I've seen other questions for this in Haskell, but I'm looking for the most optimal way to express this in a single statement (trying to understand how to work the syntax better).
We need no stinkin' mod...
zip [1..100] $ zipWith (++) (cycle ["","","fizz"]) (cycle ["","","","","buzz"])
or slightly shorter
import Data.Function(on)
zip [1..100] $ (zipWith (++) `on` cycle) ["","","fizz"] ["","","","","buzz"]
Or the brute force way:
zip [1..100] $ cycle ["","","fizz","","buzz","fizz","","","fizz","buzz","","fizz","","","fizzbuzz"]
If you insist on a one-liner:
[(x, concat $ ["fizz" | mod x 3 == 0] ++ ["buzz" | mod x 5 == 0]) | x <- [1..100]]
How's about...
fizzBuzz = [(x, fizz x ++ buzz x) | x <- [1..100]]
where fizz n | n `mod` 3 == 0 = "fizz"
| otherwise = ""
buzz n | n `mod` 5 == 0 = "buzz"
| otherwise = ""
Couldn't resist going in the other direction and making it more complicated. Look, no mod...
merge as#(a#(ia,sa):as') bs#(b#(ib,sb):bs') =
case compare ia ib of
LT -> a : merge as' bs
GT -> b : merge as bs'
EQ -> (ia, sa++sb) : merge as' bs'
merge as bs = as ++ bs
zz (n,s) = [(i, s) | i <- [n,2*n..]]
fizzBuzz = foldr merge [] $ map zz [(1,""), (3,"fizz"), (5,"buzz")]
Along the same lines as larsmans' answer:
fizzBuzz = [(x, f 3 "fizz" x ++ f 5 "buzz" x) | x <- [1..100]]
where f k s n | n `mod` k == 0 = s
| otherwise = ""
I think the reason why you feel like you are fighting the syntax is because you are mixing too many types.
Instead of trying to print:
[(1, ""), (2,""), (3,"Fizz")...]
Just think of printing strings:
["1","2","Fizz"...]
My attempt:
Prelude> let fizzBuzz x | x `mod` 15 == 0 = "FizzBuzz" | x `mod` 5 == 0 = "Buzz" | x `mod` 3 == 0 = "Fizz" | otherwise = show x
Prelude> [fizzBuzz x | x <-[1..100]]
["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"...]
In order to convert an Int to String you use the:
show x
Just for studying
zipWith (\a b -> b a) (map show [1..100]) $ cycle [id,id,const "fizz",id,const "buzz",const "fizz",id,id,const "fizz",const "buzz",id,const "fizz",id,id,const "fizzbuzz"]
produces
["1","2","fizz","4","buzz","fizz","7","8","fizz","buzz","11","fizz","13","14","fizzbuzz","16","17","fizz","19","buzz","fizz","22","23","fizz","buzz","26","fizz","28","29","fizzbuzz","31","32","fizz","34","buzz","fizz","37","38","fizz","buzz","41","fizz","43","44","fizzbuzz","46","47","fizz","49","buzz","fizz","52","53","fizz","buzz","56","fizz","58","59","fizzbuzz","61","62","fizz","64","buzz","fizz","67","68","fizz","buzz","71","fizz","73","74","fizzbuzz","76","77","fizz","79","buzz","fizz","82","83","fizz","buzz","86","fizz","88","89","fizzbuzz","91","92","fizz","94","buzz","fizz","97","98","fizz","buzz"]
Writer monad may look nice (if you don't like concat):
fizzBuzz = [(x, execWriter $ when (x `mod` 3 == 0) (tell "fizz") >> when (x `mod` 5 == 0) (tell "buzz")) | x <- [1..100]]
It's not particularly succinct though.

Haskell List Comprehension

I get the error "Not in scope: x" when doing as follows...
blanks :: Sudoku -> [Pos]
blanks (Sudoku su) = [ fst x | x <- posSud | isBlank (snd x) ]
where
isBlank Nothing = True
isBlank _ = False
posSud = zip ixPos (concat su)
ixPos = zip ixRows ixCols
ixCols = concat (replicate 9 [0..8])
ixRows = [floor (x / 9) | x <- [0..81]]
however, if I remove the guard of the 2:nd line GHCI compiles without giving me any errors.
Can you help me understand what I'm doing wrong?
try [ fst x | x <- posSud , isBlank (snd x) ]

Resources