Is there an empty character in Haskell? - haskell

This is my code:
reverseEncode :: Char -> String -> Int -> Char
reverseEncode _ [] _ = ?
reverseEncode c (x:xs) offset
| alphaPos c == (alphaPos x + offset) `mod` 26 = chr (((alphaPos x + offset) + 65) `mod` 26)
| otherwise = reverseEncode c xs offset
It's just a small method used in a virtual Enigma Machine. After writing the function without the second line and testing it, I got this exception:
Non-exhaustive patterns in function reverseEncode
I then realised I didn't tell the function when to stop recursing. This is how that second line of code was born. Obviously, I could just check the length of the string at each step, but it doesn't look as elegant.
Is there anything in Haskell I can put instead of '?' ? If not, is there anything I can define? Or is this something that could be done in a better way?
EDIT: I've actually tried the version with checking the length of the string, and I get the same exception. So how do I make it work?

There is no empty character. You could however use a character like the Nul character [wiki]. For example with:
reverseEncode :: Char -> String -> Int -> Char
reverseEncode _ [] _ = '\00'
reverseEncode c (x:xs) offset
| alphaPos c == sm `mod` 26 = chr ((sm + 65) `mod` 26)
| otherwise = reverseEncode c xs offset
where sm = alphaPos x + offset
But a more Haskellish approach would be to change the return type. For example by using a Maybe Char instead. This is often used for "computations that can fail". So we could do this with:
reverseEncode :: Char -> String -> Int -> Maybe Char
reverseEncode _ [] _ = Nothing
reverseEncode c (x:xs) offset
| alphaPos c == sm `mod` 26 = Just (chr ((sm + 65) `mod` 26))
| otherwise = reverseEncode c xs offset
where sm = alphaPos x + offset
Here the Nothing thus means we reached the end of the list without meeting the condition, and Just x means that the computation resulted in an answer x.

Related

convert string of digits to int in Haskell

I am trying to write this function in Haskell called scanString, which takes a string and convert it into int if it's composed of only digits and should return 0 otherwise.
For example, scanString "123" = 123 but scanString "12a" = 0.
Here's my implementation so far:
scanChar :: Char -> Int
scanChar c
| 48 <= fromEnum c && fromEnum c <= 57 = (fromEnum c) - fromEnum '0'
| otherwise = 0
scanString :: String -> Int
scanString str = case str of
[] -> 0
x:xs
| 48 <= fromEnum x && fromEnum x <= 57 ->
((scanChar x) * (10 ^ ((length str) -1 ))) + scanString xs
| otherwise -> 0
This code does not do the right thing as scanString "3a" would give 30.
Is there a way (like in Java or Python) where one can simply terminate a function and return a value? Of course, advice on the implementation on this function would be awesome!
Thanks in advance!
The main problem here I think is that you let scanChar :: Char -> Int return both a zero for the zero character ('0') as well as for other characters. As a result the scanString has to include extra logic and this makes it only more complex.
So we can clean the scanChar by for instance returning a -1 (or we could let it return a Maybe Int and let it return Nothing, regardless how you exactly specify it, the key is to try to encapsulate the checking logic in one function, such that we no longer have to care about it). So for example:
scanChar :: Char -> Int
scanChar c | '0' <= c && c <= '9' = fromEnum c - fromEnum '0'
| otherwise = -1
So now we can encapsulate all the digit parsing logic in scanChar. Now we still need to implement scanString :: String -> Int. This can be done by writing an extra function that works with an accumulator. For example:
scanString :: String -> Int
scanString = go 0
where go a s = ...
So here go acts as a function to emulate some sort of while loop. The a parameter is the accumulator, a parameter we pass through recursive calls and each time we can update it with more data. Initially we set it to zero.
The go function has basically three cases:
the end of the string is reached, we can return the accumulator;
the first character of the string is not a digit, we return 0; and
the first character of the string is a digit, we multiply the accumulator with 10, add the parsed value, and perform recursion on the tail of the string.
We can thus implement those three cases like:
scanString :: String -> Int
scanString = go 0
where go a [] = a
go a (x:xs) | 0 <= sc && sc <= 9 = go (10*a+sc) xs
| otherwise = 0
where sc = scanChar x
So you're limited by the specification of the problem that the outermost question be of type String -> Int, but that doesn't mean that your helper function scanChar can't return Maybe Int.
So let's look at doing that:
scanChar :: Char -> Maybe Int
scanChar c
| 48 <= fromEnum c && fromEnum c <= 57 = Just $ (fromEnum c) - fromEnum '0'
| otherwise = Nothing
Now, using the approach in the other answer:
scanString :: String -> Int
scanString = go 0
where go a [] = a
go a (x:xs) = case (scanChar x) of
Nothing -> 0
Just d -> go (10*a + d) xs
where sc = scanChar x
Why not
scanString :: String -> Int
scanString x = if all (`elem` "0123456789") x
then read x :: Int
else 0
Note: it will not read negative integers.
Or:
import Data.Char (isDigit)
scanString' :: String -> Int
scanString' x = if all isDigit x
then read x :: Int
else 0
Also a simple solution here using readMaybe.
You can make the following into a function with one parameter that is a string. This function will take only digits out of the string and pack them into another string which is then then converted.
[read [d | d <- "12a", elem d "1234567890"] :: Int] !! 0
Yields 12

Returning the temporary values of a recursion function at base case in Haskell

I am new to Haskell and am trying to learn by implementing the Needleman-Wunsch algorithm.
Right now, I'm building the table and then the algorithm recursively goes backwards taking the optimal letter for a better score.
However, the base case returns an empty string at the moment.
Here is the code:
type AlignmentType = (String, String)
optAlignments :: String -> String -> [AlignmentType]
optAlignments xs ys = optLen (length xs) (length ys)
where
optLen i j = optTable!!i!!j
optTable = [[ optEntry i j | j<-[0..]] | i<-[0..] ]
optEntry :: Int -> Int -> [AlignmentType]
optEntry _ 0 = []
optEntry 0 _ = []
optEntry i j
| x == y = [([b],[c]) | (b:bs,c:cs) <- optLen (i-1) (j-1)]
| otherwise = max (optLen i (j-1)) (optLen (i-1) j) --to be fixed
where
x = xs!!(i-1)
y = ys!!(j-1)
So my question is, how can I return the values in [([b],[c]) | (b:bs,c:cs) <- optLen (i-1) (j-1)] after the recursion has ended?

Haskell Error Not in scope: data constructor Otherwise

I am trying to create a shift function using let2nat and nat2let functions.
This shift function applies a shift factor in the range 0 to 25 to a lower-case letter in the range ā€™aā€™ to ā€™zā€™. Characters outside this range, such as upper-case letters and punctuation, should be returned unshifted. Make sure your function wraps around at the end of the alphabet.
module Kaan where
import Data.Char
let2nat :: Char -> Int
let2nat x = (ord x) - 97
nat2let :: Int -> Char
m = ['a'..'z']
nat2let x = m !! x
shift :: Int -> Char -> Char
shift x y
| (x + let2nat y <= 25) && (x + let2nat y >= 0) = nat2let x + let2nat y
| (x + let2nat y) > 25 = nat2let (x+let2nat y) `mod` 25
| Otherwise = y
main = do
print $ let2nat 'h'
This is what I am getting : Not in scope: data constructor Otherwise`
The binding is named otherwise with a lowercase o. otherwise is defined to be the same as True in the Prelude.
Incidentally, anything (at a value-level) that begins with an uppercase character is a data constructor not a normal binding like otherwise.

Haskell passing empty Character to a function

I'm working in Haskell in two functions:
Basically I want to get the character before matching a specific character in a given string
This is my code:
before :: Char -> [Char] -> Char
before x str = trackelement x ' ' str
trackelement :: Char -> Char -> [Char] -> Char
trackelement x y (z:zs)
| x == z = y
| otherwise = trackelement x z (zs)
My problem is when I try: before 'l' "luis"
The answer is : ' ' (of course, before 'l' there is nothing), and I would like to be '' or Nothing
I tried passing trackelement x '' str instead of trackelement x ' ' str but I have this error Syntax error on ''str
Could you suggest me something?
The answers shown already are good for getting your code to work, but they don't explain why you get the error you're receiving. The reason why that error was shown is that '' is not valid syntax, since there is no such thing as an "empty character". All characters have value, but Strings can be empty. Remember that type String = [Char], and it's very clear that there can be such a thing as an empty list, but characters always have a value. It's comparable to saying you can have an empty list of Ints, namely [], but you can't have an "empty int", whatever that would mean.
You can use a Maybe:
before :: Char -> [Char] -> Maybe Char
before x str = initialise x str
initialise x (y:xs)
| x == y = Nothing
| otherwise = trackelement x y xs
trackelement :: Char -> Char -> [Char] -> Maybe Char
trackelement x y [] = Nothing
trackelement x y (z:zs)
| x == z = Just y
| otherwise = trackelement x z zs
To take care of the corner case before 'l' "luis", we have to add a new initialiser function. It basically checks if the first character matches the searched one. If it does, we return Nothing, because we checked the first character which obviously does not have a preceding one. Else we just call trackelement and use it's result.
As Zeta mentioned, you can combine the functions, which simplifies everything and takes care of the corner case you are currently experiencing.
before _ [x] = Nothing
before a (x:y:xs)
| a == y = Just x
| otherwise = before a (y:xs)
Just using this function, you noticed you have problems when encountering a word containing more than one letter which is also searched for (before 'a' "amalia" -> Just 'm'). Currently the best solution I know of is again splitting this up into more than one function, which brings us back to the solution at the top.
Match the first two elements instead just head and tail. That way you don't even need trackelement:
before :: Eq a => a -> [a] -> Maybe a
before x (a:b:rest)
| a == x = Nothing
| b == x = Just a
| otherwise = before x (b:rest)
before _ _ = Nothing

Convert Negative-base binary to Decimal in Haskell: "Instances of .. required"

I have to write two functions converting decimal numers into a (-2)adian number system (similar to binary only with -2) and vice versa.
I already have managed to get the decimal -> (-2)adian running.
But with (-2)adian -> decimal I have a problem and just don't know where to begin.
Hope you can Help me
type NegaBinary = String
-- Function (-2)adisch --> decimal
negbin_dezi :: NegaBinary -> Integer -> Integer
negbin_dezi (xs:x) n
| (x == 0) = if ([xs] == "") then 0 else (negbin_dezi [xs] (n+1))
| (x == 1) = if ([xs] == "") then (-2)**n else (-2)**n + (negbin_dezi [xs] (n+1))
It always throws:
"Instances of (Num [Char], Floating Integer) required for definition of negbin_dezi.
Anyone an idea why it wont work?
Please please please :)
You have your list pattern-matching syntax backwards. In _ : _ the first argument is the head of the list (one element), and the second is the tail of the list (another list). e.g. x:xs matched with "abc" gives x = 'a' xs = "bc". So xs:x should be x:xs. The reason for GHC asking for an instance of Num [Char], is the comparison x == 0 (and x == 1). In this, it is trying to match the type of x (String == [Char]) with the type of 0 (Num a => a), and to do this, it requires a Num instance for String.
The fix is: negbin_dezi (x:xs) n
The problem asking for an Floating Integer instance is because (**) has type Floating a => a -> a -> a, where as you want (^) which has type (Num a, Integral b) => a -> b -> a (i.e. it is restricted to integer powers.)
Once you've done this, you'll find that your algorithm doesn't work for a few reasons:
The number 0 is different to the character '0', you should be comparing x with the characters '0' and '1' rather than the numbers 0 and 1.
xs is already a string, so [xs] is a list containing a string, which isn't what you want. This is fixed by removing the square brackets.
Possibly the ordering of the reduction is wrong.
On a different note, the duplicated if statement suggests that there is some optimisations that could happen with your code. Specifically, if you handle the empty string as part of negbin_dezi then you won't have to special case it. You could write it something like
negbin_dezi "" _ = 0
negbin_dezi (x:xs) n
| n == '0' = negbin_dezi xs (n+1)
| n == '1' = (-2)^n + negbin_dezi
(This has the bonus of meaning that the function is "more total", i.e. it is defined on more inputs.)
A few more things:
The code is "stringly-typed": your data is being represented as a string, despite having more structure. A list of booleans ([Bool]) would be much better.
The algorithm can be adapted to be cleaner. For the following, I'm assuming you are storing it like "01" = -2 "001" = 4, etc. If so, then we know that number = a + (-2) * b + (-2)^2 * c ... = a + (-2) * (b + (-2) * (c + ...)) where a,b,c,... are the digits. Looking at this, we can see the stuff inside the brackets is actually the same as the whole expression, just starting at the second digit. This is easy to express in Haskell (I'm using the list-of-bools idea.):
negbin [] = 0
negbin (x:xs) = (if x then 1 else 0) + (-2) * negbin xs
And that's the whole thing. If you aren't storing it in that order, then a call to reverse fixes that! (Being really tricky, one could write
negbin = foldr (\x n -> (if x then 1 else 0) + (-2)*n) 0
)
Some problems:
x == 0 or x == 1, but x is a Char, so you mean x == '0'.
You write (xs:x). There's no pattern for matching at the end of a list. Perhaps use a helper function that reverses the list first.
[xs] has one element, and will never be "". Use a base case instead.
Pattern matching is more helpful than equality checking.
** is for floating point powers, ^ is for integer powers
You often use [xs] where you mean xs. You don't need to put square brackets to make a list.
Here's a rewrite that works:
negbin_dezi1 :: NegaBinary -> Integer
negbin_dezi1 xs = negbin (reverse xs) 0
negbin [] _ = 0
negbin (x:xs) n
| x == '0' = negbin xs (n+1)
| x == '1' = (-2)^n + (negbin xs (n+1))
It would be nicer to use pattern matching:
negbin_dezi2 :: NegaBinary -> Integer
negbin_dezi2 xs = negbin (reverse xs) 0 where
negbin [] _ = 0
negbin ('0':xs) n = negbin xs (n+1)
negbin ('1':xs) n = (-2)^n + negbin xs (n+1)
But maybe it would be nicer to convert '0' to 0 and '1' to 1 and just multiply by that:
val :: Char -> Int
val '0' = 0
val '1' = 1
negbin_dezi3 :: NegaBinary -> Integer
negbin_dezi3 xs = negbin (reverse xs) 0 where
negbin [] _ = 0
negbin (x:xs) n = val x * (-2)^n + negbin xs (n+1)
I'd not write it that way, though:
A completely different approach is to think about the whole thing at once.
"10010" -rev> [0,1,0,0,1] -means> [ 0, 1, 0, 0, 1 ]
[(-2)^0, (-2)^1, (-2)^2, (-2)^3, (-2)^4]
so let's make both lists
powers = [(-2)^n | n <- [0..]]
coefficients = reverse.map val $ xs
and multiply them
zipWith (*) powers coefficients
then add up, giving:
negbin_dezi4 xs = sum $ zipWith (*) powers coefficients
where powers = [(-2)^n | n <- [0..]]
coefficients = reverse.map val $ xs
You could rewrite powers as map ((-2)^) [0..],
or even nicer: powers = 1:map ((-2)*) powers.
(It's nicer because it reuses previous calculations and is pleasantly clean.)
this
convB2D::NegaBinary->Integer
convB2D xs|(length xs)==0 =0
|b=='0' = convB2D(drop 1 xs)
|b=='1' = val+convB2D(drop 1 xs)
|otherwise= error "invalid character "
where b=head xs
val=(-2)^((length xs)-1)
worked for me.
I on the other hand have problems to convert dec->nbin :D

Resources