test :: String -> String -> Int
test' x y n = n
test' "" (y:ys) n = error "error"
test' (x:xs) "" n = error "error"
test' (x:xs) (y:ys) n =
if x == y
then test' xs ys n
else test' xs ys (n+1)
test a b = test' a b 0
When I compile this, I get this output:
Warning: Pattern match(es) are overlapped
And the answer is always "0", which is not what I intended. What is the problem with the code and how to fix it?
test' x y n = n will match for every call, the other patterns won't be considered. I think this case should be test' "" "" n = n. You get the same result if you move your original line at the end (when all other cases fail), but then you should write test' _ _ n = n which shows that you deliberately ignore some of the arguments.
[Edit]
A shorter solution would be:
test a b | length a == length b = sum $ map fromEnum $ zipWith (/=) a b
| otherwise = error "error"
The zipWith expression generates a list of Bool which is True for every difference. The function fromEnum maps False to 0 and True to 1.
The patterns are tried in order. The first of your patterns for test' always matches, so that case is always used. The first case should probably be
test' "" "" n = n
instead.
Related
I am currently a newbie just starting out.
My code :
atIndex :: [a] -> Int -> a
atIndex [] _ = error "error"
atIndex (xs) n = head (drop n xs)
The first argument is my array and the second my index (ex: atIndex [1,2,3] 1; I will get 2).
I want to know how can I send an error or message if my index is out of range of the array ?
example: atIndex [1,2,3] -1 or atIndex [1,2,3] 3 and get "error, your index is out of range".
You can work with a guard so:
atIndex :: [a] -> Int -> a
atIndex [] _ = error "error"
atIndex (x:_) 0 = …
atIndex (_:xs) n
| n < 0 = …
| otherwise = atIndex … …
In Haskell, one howeve usually does not work with errors, but encodes it in the output, by using a Maybe a or Either String a type for example where Nothing/Left "error message" is used if the input is invalid, and Just x/Right x in case the input is valid with x the result wrapped in a Just or Right, so:
atIndex :: [a] -> Int -> Maybe a
atIndex [] _ = Nothing
atIndex (x:_) 0 = Just …
atIndex (_:xs) n
| n < 0 = Nothing
| otherwise = atIndex … …
For variety, this is what the code looks like when using if / else and Either.
Note 1. When using guards you don't have = in the declaration, whereas you do with if / else.
Note 2. As with Maybe, where the return type is Just value or Nothing, with Either the return type is Left error or Right value. Unlike Maybe, Either includes an error message.
atIndex :: [a] -> Int -> Either String a
atIndex [] _ = Left "Error"
atIndex xs n =
if n >=0 && n < length(xs) then
Right $ head (drop n xs)
else
Left "Error"
If you just want an error on invalid index, the built-in indexing function (!!) already does this. Its definition, found on page 118 of the Haskell 2010 Language Report, is as follows:
(!!) :: [a] -> Int -> a
xs !! n | n < 0 = error "Prelude.!!: negative index"
[] !! _ = error "Prelude.!!: index too large"
(x:_) !! 0 = x
(_:xs) !! n = xs !! (n-1)
Other options are to use a Maybe or Either to represent the result. The implementation would be similar to the above, but returning Nothing/Left on errors and returning Just/Right otherwise.
Note that head is a partial function, and listToMaybe should be used instead when the list could be empty. Here are some implementations using drop like your function:
atIndexMaybe :: [a] -> Int -> Maybe a
atIndexMaybe xs n
| n < 0 = Nothing
| otherwise = listToMaybe (drop n xs)
atIndexEither :: [a] -> Int -> Either String a
atIndexEither xs n
| n < 0 = Left "Negative index"
| otherwise = case drop n xs of
[] -> Left "Index out of range"
(x:_) -> Right x
I'm attempting to create a replace function and the code below creates the error described in the post title in the first line of non-commented code following it. I have no idea as to why this is happening, so any help would be greatly appreciated.
replace [] t r n = []
replace [] _ _ _ = []
replace xs _ _ 0 = xs
replace (x:xs) t r n
| x == t = r:(replace [xs] t r (n-1))
| otherwise x (replace [xs] t r n)
There are some problems here: all the parts of the definition should start at the same column, so you should unindent the lines after the first one. Furthermore you need to write a = after the otherwise. xs is a list, so you call replace with replace xs, not replace [xs]. For the last guard you are constructing a list, so x : (…), not x (…). The second clause also does not make much sense, since that is equivalent to the first one.
You thus can implement this as:
replace :: (Integral n, Eq a) => [a] -> a -> a -> n -> [a]
replace [] _ _ _ = []
replace xs _ _ 0 = xs
replace (x:xs) t r n
| x == t = r : replace xs t r (n-1)
| otherwise = x : replace xs t r n
I'm trying the solve the first question in Advent of Code 2017, and come up with the following solution to calculate the needed value:
checkRepetition :: [Int] -> Bool
checkRepetition [] = False
checkRepetition (x:xs)
| x == ( head xs ) = True
| otherwise = False
test :: [Int] -> Int
test [] = 0
test [x] = 0
test xs
| checkRepetition xs == True = ((head xs)*a) + (test (drop a xs))
| otherwise = test (tail xs)
where
a = (go (tail xs)) + 1
go :: [Int] -> Int
go [] = 0
go xs
| checkRepetition xs == True = 1 + ( go (tail xs) )
| otherwise = 0
However, when I give an input that contains repetitive numbers such as [1,3,3], it gives the error
*** Exception: Prelude.head: empty list
However, for 1.5 hours, I couldn't figure out exactly where this error is generated. I mean any function that is used in test function have a definition for [], but still it throws this error, so what is the problem ?
Note that, I have checked out this question, and in the given answer, it is advised not to use head and tail functions, but I have tested those function for various inputs, and they do not throw any error, so what exactly is the problem ?
I would appreciate any help or hint.
As was pointed out in the comments, the issue is here:
checkRepetition (x:xs)
| x == ( head xs ) = True
xs is not guaranteed to be a non-empty list (a one-element list is written as x:[], so that (x:xs) pattern matches that xs = []) and calling head on an empty list is a runtime error.
You can deal with this by changing your pattern to only match on a 2+ element list.
checkRepetition [] = False
checkRepetition [_] = False
checkRepetition (x1:x2:_) = x1 == x2
-- No need for the alternations on this function, by the way.
That said, your algorithm seems needlessly complex. All you have to do is check if the next value is equal, and if so then add the current value to the total. Assuming you can get your String -> [Int] on your own, consider something like:
filteredSum :: [Int] -> Int
filteredSum [] = 0 -- by definition, zero- and one-element lists
filteredSum [_] = 0 -- cannot produce a sum, so special case them here
filteredSum xss#(first:_) = go xss
where
-- handle all recursive cases
go (x1:xs#(x2:_)) | x1 == x2 = x1 + go xs
| otherwise = go xs
-- base case
go [x] | x == first = x -- handles last character wrapping
| otherwise = 0 -- and if it doesn't wrap
-- this should be unreachable
go [] = 0
For what it's worth, I think it's better to work in the Maybe monad and operate over Maybe [Int] -> Maybe Int, but luckily that's easy since Maybe is a functor.
digitToMaybeInt :: Char -> Maybe Int
digitToMaybeInt '0' = Just 0
digitToMaybeInt '1' = Just 1
digitToMaybeInt '2' = Just 2
digitToMaybeInt '3' = Just 3
digitToMaybeInt '4' = Just 4
digitToMaybeInt '5' = Just 5
digitToMaybeInt '6' = Just 6
digitToMaybeInt '7' = Just 7
digitToMaybeInt '8' = Just 8
digitToMaybeInt '9' = Just 9
digitToMaybeInt _ = Nothing
maybeResult :: Maybe Int
maybeResult = fmap filteredSum . traverse digitToMaybeInt $ input
result :: Int
result = case maybeResult of
Just x -> x
Nothing -> 0
-- this is equivalent to `maybe 0 id maybeResult`
Thank you for the link. I went there first to glean the purpose.
I assume the input will be a string. The helper function below constructs a numeric list to be used to sum if predicate is True, that is, the zipped values are equal, that is, each number compared to each successive number (the pair).
The helper function 'nl' invokes the primary function 'invcap' Inverse Captcha with a list of numbers.
The nl function is a list comprehension. The invcap function is a list comprehension. Perhaps the logic in this question is at fault. Overly complicated logic is more likely to introduce errors. Proofs are very much easier when logic is not cumbersome.
The primary function "invcap"
invcap l = sum [ x | (x,y) <- zip l $ (tail l) ++ [head l], x == y]
The helper function that converts a string to a list of digits and invokes invcap with a list of numeric digits.
nl cs = invcap [ read [t] :: Int | t <- cs]
Invocation examples
Prelude> nl "91212129" ......
9 ' ' ' ' ' ' ' ' ' ' ' ' '
Prelude> nl "1122" ......
3
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
The following two functions behave differently when given an empty string:
guardMatch l#(x:xs)
| x == '-' = "negative " ++ xs
| otherwise = l
patternMatch ('-':xs) = "negative " ++ xs
patternMatch l = l
Here my output:
*Main> guardMatch ""
"*** Exception: matching.hs:(1,1)-(3,20): Non-exhaustive patterns in function guardMatch
*Main> patternMatch ""
""
Question: why does not the 'otherwise' close catch the empty string?
The otherwise is within the scope of the pattern l#(x:xs), which can only match a non-empty string. It might help to see what this (effectively) translates to internally:
guardMatch l = case l of
(x :xs) -> if x == '-' then "negative " ++ xs else l
patternMatch l = case l of
('-':xs) -> "negative " ++ xs
_ -> l
(Actually, I think the if is translated to a case + guard instead of the other way around.)
A guard is always evaluated after the pattern. This is - the guard is tried iff the pattern succeeds. In your case, the pattern (x:xs) excludes the empty string, so the guards are not even tried, as the pattern fails.
The other two answers are totally right of course, but here's another way to think about it: What if you had written this?
guardMatch l#(x:xs)
| x == '-' = "negative " ++ xs
| otherwise = [x]
What would you expect guardMatch "" to be?