Comparing tuples in haskell - haskell

I was just writing a function that would take in an input of a tuple where the first element would be a string and the second element would be a number. So something like (String, Int). This function was supposed to compare the "Int" value to check if it was bigger or less than a certain value. Just playing around with it, I realised that the following definition for the function works.
check :: (String, Int) -> Grade
check (course, mark)
| (course, mark) < (course, 50) = Fail
| otherwise = Pass
This function seems to work as it checks the integer values. But I don't understand why this works? What is happening to the String in the tuple? How is the string getting compared against it self? I would appreciate if someone could help me understand what is going on.

The definition of < for tuples is equivalent to the following:
instance (Ord a, Ord b) => Ord (a,b) where
(x,y) < (x',y')
| x<x' = True
| x==x' = y<y'
| otherwise = False
This is called lexicographic ordering.
In your code, you are trivially always in the x==x' branch, because course==course holds (for finite strings, at least). It is an unnecessary comparison, better and equivalent would be to just compare the mark directly, and not even match on course:
check :: (String, Int) -> Grade
check (_, mark)
| mark < 50 = Fail
| otherwise = Pass

Related

How to check for the argument of a function and pass it on?

I'm trying to code a function that takes one of my own commands and its argument if it has got one and passes on the argument only. Of course "int" is not in scope, but if I try to pass it on with x (like "f (x int)") I get a parse error. I'm new to Haskell and grateful for any advice.
data Command = PushC Int | Pop | Push Int
f :: Command -> Int
f x | x == PushC int = int
| x == Pop = 1
| x == Push int = int
| otherwise = -1
I just want to check for any Integer as argument of the command and have it as output. If the command doesen't have an argument output 1.
You really should use pattern matching [Haskell-wiki] here:
f :: Command -> Int
f (PushC n) = n
f (Push n) = n
f Pop = 1
Pattern matching is more effective than using (==) :: Eq a => a -> a -> Bool, first of all, not all types are an instance of Eq, and furthermore you can not match parameters of the data constructor with Eq. You can thus not match some_val == PushC num, and hope that Haskell assigns a value to num, like Prolog does.
Usually (==) and (/=) are only used to check if two values are equal, not to discriminate between the possible data constructors and parameters of a type.
You could use a wild card (_) as last clause here, but it is probably better not to do that: if you later add an extra Command data constructor, the compiler can warn you that not all patterns are covered, and thus you can provide the correct expression. If on the other hand, you use a wildcard, then that clause will automatically be matched with that data constructor, and this might not be the intended effect.

Haskell Programming Assignment, "Couldn't match expected type ‘Int’ with actual type ‘[a0] -> Int’ "and a few more Errors

The assignment I have: A function numOccurences that takes a value and a list, returning the number of times that value appears in the list. I am learning haskell and am getting frustrated, this is my code for this:
numOccurences:: b -> [a] -> Int
numOccurences n [ls]
|([ls] !! n==True) = (numOccurences(n (tail [ls])))+1
|otherwise = 0
The errors I am getting are as follows:
https://imgur.com/a/0lTBn
A few pointers:
First, in your type signature, using different type variables (i.e. b and a) creates the possibility that you could look for occurrences of a value of one type, in a list with another type, which in this case is not what you want. So instead of two type variables, you just want to use one.
Second, whatever the concrete type of your list is, whether it's [Char], [Int], etc., it needs to be equatable (i.e. it needs to derive the Eq typeclass), so it makes sense to use the class constraint (Eq a) => in your type signature.
Third, since we're traversing a list, let's use pattern matching to safely break off the first element of the list for comparison, and let's also add a base case (i.e. what we do with an empty list), since we're using recursion, and we only want the recursive pattern to match as long as there are elements in our list.
Lastly, try to avoid using indexing (i.e. !!), where you can avoid it, and use pattern matching instead, as it's safer and easier to reason about.
Here's how your modified function might look, based on the above pointers:
numOccurences :: (Eq a) => a -> [a] -> Int
numOccurences _ [] = 0
numOccurences n (x:xs)
| n == x = 1 + numOccurences n xs
| otherwise = numOccurences n xs

Why am I receiving this syntax error - possibly due to bad layout?

I've just started trying to learn haskell and functional programming. I'm trying to write this function that will convert a binary string into its decimal equivalent. Please could someone point out why I am constantly getting the error:
"BinToDecimal.hs":19 - Syntax error in expression (unexpected `}', possibly due to bad layout)
module BinToDecimal where
total :: [Integer]
total = []
binToDecimal :: String -> Integer
binToDecimal a = if (null a) then (sum total)
else if (head a == "0") then binToDecimal (tail a)
else if (head a == "1") then total ++ (2^((length a)-1))
binToDecimal (tail a)
So, total may not be doing what you think it is. total isn't a mutable variable that you're changing, it will always be the empty list []. I think your function should include another parameter for the list you're building up. I would implement this by having binToDecimal call a helper function with the starting case of an empty list, like so:
binToDecimal :: String -> Integer
binToDecimal s = binToDecimal' s []
binToDecimal' :: String -> [Integer] -> Integer
-- implement binToDecimal' here
In addition to what #Sibi has said, I would highly recommend using pattern matching rather than nested if-else. For example, I'd implement the base case of binToDecimal' like so:
binToDecimal' :: String -> [Integer] -> Integer
binToDecimal' "" total = sum total -- when the first argument is the empty string, just sum total. Equivalent to `if (null a) then (sum total)`
-- Include other pattern matching statements here to handle your other if/else cases
If you think it'd be helpful, I can provide the full implementation of this function instead of giving tips.
Ok, let me give you hints to get you started:
You cannot do head a == "0" because "0" is String. Since the type of a is [Char], the type of head a is Char and you have to compare it with an Char. You can solve it using head a == '0'. Note that "0" and '0' are different.
Similarly, rectify your type error in head a == "1"
This won't typecheck: total ++ (2^((length a)-1)) because the type of total is [Integer] and the type of (2^((length a)-1)) is Integer. For the function ++ to typecheck both arguments passed to it should be list of the same type.
You are possible missing an else block at last. (before the code binToDecimal (tail a))
That being said, instead of using nested if else expression, try to use guards as they will increase the readability greatly.
There are many things we can improve here (but no worries, this is perfectly normal in the beginning, there is so much to learn when we start Haskell!!!).
First of all, a string is definitely not an appropriate way to represent a binary, because nothing prevents us to write "éaldkgjasdg" in place of a proper binary. So, the first thing is to define our binary type:
data Binary = Zero | One deriving (Show)
We just say that it can be Zero or One. The deriving (Show) will allow us to have the result displayed when run in GHCI.
In Haskell to solve problem we tend to start with a more general case to dive then in our particular case. The thing we need here is a function with an additional argument which holds the total. Note the use of pattern matching instead of ifs which makes the function easier to read.
binToDecimalAcc :: [Binary] -> Integer -> Integer
binToDecimalAcc [] acc = acc
binToDecimalAcc (Zero:xs) acc = binToDecimalAcc xs acc
binToDecimalAcc (One:xs) acc = binToDecimalAcc xs $ acc + 2^(length xs)
Finally, since we want only to have to pass a single parameter we define or specific function where the acc value is 0:
binToDecimal :: [Binary] -> Integer
binToDecimal binaries = binToDecimalAcc binaries 0
We can run a test in GHCI:
test1 = binToDecimal [One, Zero, One, Zero, One, Zero]
> 42
OK, all fine, but what if you really need to convert a string to a decimal? Then, we need a function able to convert this string to a binary. The problem as seen above is that not all strings are proper binaries. To handle this, we will need to report some sort of error. The solution I will use here is very common in Haskell: it is to use "Maybe". If the string is correct, it will return "Just result" else it will return "Nothing". Let's see that in practice!
The first function we will write is to convert a char to a binary. As discussed above, Nothing represents an error.
charToBinary :: Char -> Maybe Binary
charToBinary '0' = Just Zero
charToBinary '1' = Just One
charToBinary _ = Nothing
Then, we can write a function for a whole string (which is a list of Char). So [Char] is equivalent to String. I used it here to make clearer that we are dealing with a list.
stringToBinary :: [Char] -> Maybe [Binary]
stringToBinary [] = Just []
stringToBinary chars = mapM charToBinary chars
The function mapM is a kind of variation of map which acts on monads (Maybe is actually a monad). To learn about monads I recommend reading Learn You a Haskell for Great Good!
http://learnyouahaskell.com/a-fistful-of-monads
We can notice once more that if there are any errors, Nothing will be returned.
A dedicated function to convert strings holding binaries can now be written.
binStringToDecimal :: [Char] -> Maybe Integer
binStringToDecimal = fmap binToDecimal . stringToBinary
The use of the "." function allow us to define this function as an equality with another function, so we do not need to mention the parameter (point free notation).
The fmap function allow us to run binToDecimal (which expect a [Binary] as argument) on the return of stringToBinary (which is of type "Maybe [Binary]"). Once again, Learn you a Haskell... is a very good reference to learn more about fmap:
http://learnyouahaskell.com/functors-applicative-functors-and-monoids
Now, we can run a second test:
test2 = binStringToDecimal "101010"
> Just 42
And finally, we can test our error handling system with a mistake in the string:
test3 = binStringToDecimal "102010"
> Nothing

Haskell Confusing Type Classes / Polymorphism

So basically I've past learning this part way back a month ago, and I can do more complicated stuff but I still don't understand when I need "Ord" or "Eq" etc in my type definitions. When I look it up online its just so confusing to me for some reason.
E.g.
my_min :: Ord a => a -> a -> a
my_min n1 n2 = if n1<n2 then n1 else n2
Why does this need Ord? Can you give an example of when you need Eq as well (a very simple one)? I need a very clear, basic explanation of when you need to put these, what to look out for to do that, and how to avoid using these at all if possible.
Usually I just need something like "[Int] -> Int -> [Int]" so i know ok this function takes an integer list and an integer, and returns an integer list. But when it includes Eq or Ord I have no idea.
What about this Eq type in this example I found in my lecture notes about finding two lists is identical, how does it apply?
identical :: Eq a =>[a]->[a]->Bool
identical [] [] = True
identical [] _ = False
identical _ [] = False
identical (h1:t1) (h2:t2) =
if h1==h2
then (identical t1 t2)
else False
Thank you.
Ord implies that the thing can be ordered, which means that you can say a is smaller (or greater) than b. Using only Eq is like saying: I know that these two items are not the same, but I cannot say which one is greater or smaller. For example if you take a traffic light as a data type:
data TLight = Red | Yellow | Green deriving (Show, Eq)
instance Eq TLight where
Green == Green = True
Yellow == Yellow = True
Red == Red = True
_ == _ = False
Now we can say: Red is unequal to Yellow but we cannot say what is greater. This is the reason why you could not use TLight in your my_min. You cannot say which one is greater.
To your second question: "Is there any case where you have to use Eq and Ord?":
Ord implies Eq. This means that if a type can be ordered, you can also check it for equality.
You said you have mostly dealt with [Int] -> Int -> [Int] and you then knew it takes a list of integer and an integer and returns an integer. Now if you want to generalise your function you have to ask yourself: Do the possible types I want to use in my function need any special functionality? like if they have to be able to be ordered or equated.
Lets do a few examples: Say we want to write a function which takes a list of type a and an element of type a and returns the lisy with the element consed onto it. How would it's type signature look like? Lets start with simply this:
consfunc :: [a] -> a -> [a]
Do we need any more functionality? No! Our type a can be anything because we do not need it to be able to be ordered simple because that is mot what our function should do.
Now what if we want to take a list and an element and check if the element is in the list already? The beginning type signature is:
elemfunc :: [a] -> a -> Bool
Now does our element have to be able to do something special? Yes it does, we have to be able to check if it is equal to any element in the list, which says that our type a has to be equatable, so our type signature looks like this:
elemfunc :: (Eq a) => [a] -> a -> Bool
Now what if we want to take a list and a element and insert it if it is smaller than the first element? Can you guess how the type signature would look like?
Lets begin with the standard again and ask ourselves: Do we need more than just knowing that the element and the list have to be of the same type: Yes, becuase our condition needs to perform a test that requires our type to be ordered, we have to include Ord in our type signature:
conditionalconsfunc :: (Ord a) => [a] -> a -> [a]
Edit:
Well you want to see if two lists are identical, so there are two things you have to look out for:
Your lists have to contain the same type and the things inside the list have to be equatable, hence the Eq.
If you are working with fixed types like Int, you never need class constraints. These only arise when working with polymorphic code.
You need Eq if you ever use the == or /= functions, or if you call any other functions that do. (I.e., if you call a function that has Eq in its type, then your type needs to have Eq as well.)
You need Ord if you ever use <, >, compare or similar functions. (Again, or if you call something that does.)
Note that you do not need Eq if you only do pattern matching. Thus, the following are different:
factorial 1 = 1
factorial n = n * factorial (n-1)
-- Only needs Num.
factorial n = if n == 1 then 1 else n * factorial (n-1)
-- Needs Num and Eq.
factorial n = if n < 2 then 1 else n * factorial (n-1)
-- Needs Num, Eq and Ord. (But Ord implies Eq automatically.)

implementing indexOf in Haskell

I'm going through the Learn You a Haskell tutorial and attempted to modify the elem' function from the section on Recursion.
The original elem' function is:
elem' :: (Eq a) => a -> [a] -> Bool
elem' a [] = False
elem' a (x:xs)
| a == x = True
| otherwise = a `elem'` xs
My indexOf function is:
indexOf :: (Eq a, Integral s) => a -> [a] -> s -> s
indexOf _ [] _ = -1
indexOf a (x:xs) s
| a == x = s
| otherwise = indexOf a xs s+1
The function should return either the index of the element in the list, or -1 if the element is not found.
At the end of my .hs file I test the function with:
main = putStrLn(show(indexOf 7 [1,2,3] 0))
The function works correctly for finding values that appear in the list. However, for the test written above, instead of returning -1, it prints 2. The return value seems to always be the list length minus one.
After encountering the edge condition (empty list), I would expect the -1 return value to propagate all the way back upwards through the call stack. Where's my mistake?
You've got a precedence problem. Function application binds more tightly than (+), so the otherwise case is being parsed as (index' a xs s) + 1.
There is one simple change you could make to the example above, which would be almost guaranteed to fix your bug. Change the return type to Maybe a, and return Nothing upon failure. While this alone won't fix your bug, it gives the compiler enough information that it will lead you down the correct path that you will be able to fix it yourself.
Returning -1 on failure is a very "c" thing to do, and it is error prone. In your case, the compiler is confusing -1 with an actual array index, which can be added to as you go back up through the recursive calls. (I can see that this was not your intention from the signature, but this is how the compiler interpreted what you have done).
(One added advantage- Once you master the art of using correct types, you will soon realize how hard it is to work with functions of the type a->Maybe b, or more generally a->m b, where m is some wrapper type.... This will bring you to the doorstep of understanding what and why we use monads).

Resources