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
Related
I have the following exercise:
I need do write a function which checks if the entered Int-value is >= 4 and <= 6 and does not start with 0. Then the function should give back a True.
This is the function I have to implement: (pinCheck :: Int -> Bool is given)
pinCheck :: Int -> Bool
pinCheck x
| (( last (ab)) /= '0' ) && len <= 6 && len >= 4 = True
| otherwise = False
where
len = length (digs x)
ab = reverse (show x)
digs :: Integral x => x -> [x]
digs 0 = []
digs x = digs (x `div`10) ++ [x `mod` 10]
I have to check a testcase with the given Int-value 0323. It has to give out false, but it gives out true.
I wanted to convert the Int to a String and then check with head if the first value is /= 0. But while converting, it cuts off the 0 automatically.
I didn't know that the show function did that, so I wanted first to reverse the converted string and then check the last element if it is /= 0 but...
Now my question: Is it with my fundamental program code possible to solve this problem?
No, it is not possible. If you want to preserve presentational details about the number, have pinCheck take a String instead of an Int.
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.
What I got is
digitIndex :: String -> Int
digitIndex [] = 1
digitIndex (x:xs) =
if
isDigit x == True
then
-- Count list
else
-- Create list with x(x is not a digit)
What my idea is is to make a list with all the x that he is passing so when he passes a digit he only needs to count the list and that will be the position of the digit(when you count a +1).
Only thing is I don't know how to get the job more done. Can you guys help me out with tips?
You can use findIndex:
import Data.List
digitIndex :: String -> Int
digitIndex = maybe 0 id . findIndex isDigit
Just the normal recursion:
digitIndex :: String -> Int
digitIndex [] = 0
digitIndex (x:xs) = if isDigit x
then 1
else 1 + digitIndex xs
If the first character itself is a digit, then the function returns 1 else it just adds 1 and passes the remaining string (xs) to the function and the recursion goes on.
Also note that the above function doesn't work properly when the String doesn't have a number at all.
And also checking isDigit == True isn't necessary.
I'm trying to recursively find the ith positive integer for which the predicate is true. I need to keep it general for every function.
ithTrueValue :: (Int -> Bool) -> Int-> Int
ithTrueValue func i
| i < 1 = error "Integer MUST BE greater than 0"
| ithTrueValue func i = 1 + ithTrueValue(func i-1 )
| otherwise = ithTrueValue(func i-1)
I get a type error:
ERROR file:.\new 10.hs:6 - Type error in guard
*** Term : ithTrueValue func i
*** Type : Int
*** Does not match : Bool
The problem is that ithTrueValue func i isn't boolean, it's an integer. I think there are really 4 cases to deal with here,
i is an insane value, like -1 or similar
The predicate is true at the current integer,
The predicate is false at the current integer
The predicate is true and this is the ith time it's true.
With that in mind let's restructure your code a bit
ithTrueValue f i = go 0 f i
so we're using this helper function called go which is going to count up the integers and keep track of what integer we're at
where go _ _ i | i <= 0 = error "i must be a positive integer" -- case 1.
go curr f i | f curr = if i == 1
then curr -- case 4.
else go (curr + 1) f (i - 1) -- case 2.
| otherwise = ??? -- case 3.
Where ??? is the case where the predicate is false. I'll leave it to you to figure out what to do in this case.
Now this works, but it's very.. low level. Explicit recursion is not the nicest way to write this sorta stuff. More pleasant is to rely on higher order functions, specifically
filter :: (a -> Bool) -> [a] -> [a]
So this will run down the list and leave all values where the predicate is true
ithTrueValue i f = ??? filter f [0..]
where ??? get's the ith value of the list. For this we use
(!!) :: [a] -> Int -> a
which just selects an index
ithTrueValue i f = filter f [0..] !! i
Your error is with this line:
| ithTrueValue func i = 1 + ithTrueValue(func i-1 )
^^^^^^^^^^^^^^^^^^^^^^^^^
iTruthValue takes 2 arguments, but because of the parens you're only calling it with one.
You probably wanted to write something like:
| ithTrueValue func i = 1 + ithTrueValue func (i-1)
I want to program a function that generates a String. The String contains only 1,0,s and S.
The numbers are binary numbers. Each number is separated through a s. And a number gives the length of the rest of the String. The capital S is the end of the String.
Examples:
func :: Integral a => a -> String
func 1
"1S"
func 3
"110s11s1S"
func 4
"1010s110s11s1S"
My problem is, that I don't know, how I can get the length of the tail ("s1S" -> tail, 11 -> head) and than get the new tail.
My new code:
>toBinary :: Integral a => a -> String
>toBinary 0 = []
>toBinary x
> | mod x 2 == 0 = '0' : toBinary (div x 2)
> | mod x 2 == 1 = '1' : toBinary (div x 2)
>zubinaer :: Integral a => a -> String
>zubinaer x = reverse (toBinary x)
>
>distan :: Integral a => a -> String
>distan n = if n > 0 then hilfsfunktion (n-1) "1S" else []
>
> where
> hilfsfunktion :: Integral a => a -> String -> String
> hilfsfunktion 0 s = s
> hilfsfunktion n s = hilfsfunktion (n-1) (zubinaer(length s + 1) ++ "s" ++ s )
Here my older code: http://hpaste.org/54863
I think you are tackling your problem from the wrong angle. In Haskell, one often thinks of lists. Actually, a String is just a list of Chars. Try to build your function from these bricks:
Write a function toBinary :: Integral a => a -> [Bool] that outputs a binary representation of its parameters. A 1 is True and a 0 is False
You can use map to turn the [Bool] into a String by replacing each boolean by a character 0 or 1.
You can use the syntax [1..n] to generate a list of integers from 1 to n. Use map to generate a list of binary representation strings.
Use intercalate from Data.List to create your string.
Since the tail is defined recursively (ex.: the "tail" of (f 4) is (f 3)) you can get the length of the tail by first getting the tail:
let the_tail = f (n-1) in
then calling the length function on it
length the_tail