Haskell: Polymorphic functions explanation - haskell

So i am given this
intCMP :: Int -> Int -> Ordering
intCMP a b | a == b = EQ
| a < b = LT
| otherwise = GT
intCMPRev :: Int -> Int -> Ordering
intCMPRev a b | a == b = EQ
| a < b = GT
| otherwise = LT
floatCMP :: Float -> Float -> Ordering
floatCMP a b | a == b = EQ
| a < b = LT
| otherwise = GT
I need to write this function
sort3 :: Ord a => (a -> a-> Ordering) -> [a] -> [a]
sort3 cmp xs =
Which will sort 3 or less elements by comparison. No recursion. I was wondering how this works as far as passing say intCMP. Why would you pass that into the sort function? Does it serve a purpose when sorting and returning the sorted list? I'm not really sure how to do the comparisons manually like that without any sort of recursive call, so I'm just trying to understand it better.
I was thinking of doing 3 comparisons and then moving the element to a certain position in the list, but i really don't know how i could even do this in haskell. Any clues on how to start this would be great. Maybe some sort of pattern?
Thanks.

Partial answer to the first part of your question:
Passing in intCMP to sort3 lets you control the way the sorting is done. Presumably, sort3 intCMP [7,3,6] will return [3,6,7], whereas sort3 intCMPRev [7,3,6] will return [7,6,3]. You could even make your own weird sorting functions like first all the even numbers and then all the odd ones in descending order, like so:
intCMPWeird :: Int -> Int -> Ordering
intCMPWeird a b
| even a && even b = intCMP a b -- even numbers compare as usual
| odd a && odd b = intCMPRev a b -- odd numbers compare in reverse order
| even a && odd b = LT -- evens are all 'smaller' than odds
| odd a && even b = GT -- odds are all 'greater' than evens
Using this, sort3 intCMPWeird [7,3,6] should give [6,7,3].
What happens during typechecking when you pass one of the intCMP... functions into sort3 is (in a very small nutshell) that the compiler tries to match the type of sort3's first argument (a -> a -> Ordering) with the type of the supplied value (Int -> Int -> Ordering) and succeeds in doing that, by making a equal to Int. Then it needs to check whether the constraint Ord a is satisfied for Int, which works! Finally the compiler can figure out that the type of sort3 intCMP is [Int] -> [Int]. Similarly, sort3 floatCMP has type [Float] -> [Float].
I'm not 100% sure why the Ord constraint is on the type of sort3, since you can get the needed information from the passed-in comparison function - are you sure you've typed that correctly?
EDIT: Hint on how to use a where clause to get a readable definition, you still have to fill in some bits and add some more clauses:
sort3 cmp [x,y,z]
| x <= y && somethingElse1 = listWithXyzInSomeOrder1
| x <= z && somethingElse2 = listWithXyzInSomeOrder2
where a <= b = cmp a b /= GT

Here's a hint:
If you have an empty list, clearly the result of sorting it will be an empty list.
Likewise, a list with just a single element is also already sorted.
If you have a 2-element list, there are only 2 possible orderings, hence only 2 possible return values from your function.
If you have a 3-element list, there are 6 possible orderings (the first element can be 1 of 3 input elements, the next element can be 1 of the 2 remaining, leaving only 1 choice for the last element). You can easily write down the 6 different conditions, causing you to return 1 of the 6 possible lists of the 3 elements.

You're not writing polymorphic functions (which is by definition a function that takes more than one type). Write one first:
cmp :: Ord a => a -> a -> Ordering
cmp x y =
| x == y = EQ
| x < y = LT
| otherwise = GT
You would write the above that way the functionality that compares the elements in the sort, need not be a part of the sort. To sort a list is by nature recursive: at least if length is undefined. To achieve this simply write a sort that can make use of your custom comparison, here is quick sort though you could write a different type of sort.
sort3 :: (Ord a) => [a] -> [a]
sort3 [] = []
sort3 (x:xs) =
let smallerSorted = filter (<=)
biggerSorted = filter(>)
in smallerSorted ++ [x] ++ biggerSorted

Related

Haskell shift list

I want to shift a list by n elements to the left. Why do I get an error if I want to change the order from (x:xs) to (xs:x)?
shift n list#(x:xs)
| n == 0 = list
| otherwise = shift (n-1) (xs:x) -- (xs:x) error
Occurs check: cannot construct the infinite type: a ~ [a]
I don't know how to interpret this error. Maybe someone of you can help me.
Thank you very much.
EDIT: As it was already mentioned, the correct term to use is rotate and not shift
Why do I get an error if I want to change the order from (x:xs) to (xs:x)?
Because the types do not match. The type of (:) is (:) :: a -> [a] -> [a]. It thus expects an element x (type a) and a list with the rest of the elements (type [a]). You can not just use (:) in the opposite way.
You can use the (++) :: [a] -> [a] -> [a] to concatenate two lists together. We can thus rotate to the left by dropping n elements from the list and concatenating this with the first n elements of the list to this.
rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
| otherwise = drop n list ++ take n list
or we can, like #YannVernier says, use splitAt :: Int -> [a] -> ([a], [a]):
rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
| otherwise = lb ++ la
where (la, lb) = splitAt n list
or without mentioning the list parameter:
rotateL :: Int -> [a] -> [a]
rotateL 0 = id
rotateL n | n < 0 = error "Negative index"
| otherwise= uncurry (flip (++)) . splitAt n
Note: based on how your attempt, I think you actually want to rotate the list to the left, not shift it, since that would mean that you simply drop the first n elements, and fill it perhaps with some extra value.
Note: in case n is larger than the length of the list, then the rotateL will act as an identity function. That might not be the desired behavior. I leave it as an exercise to fix this edge-case.
It's not the names that define the types, but the positions in a function call, or type declarations. If we check the type of :, we see that the second argument is a list:
Prelude> :t (:)
(:) :: a -> [a] -> [a]
So pattern matching on this constructor will always give you the head and tail, not the init and last. Thus, using both x:xs and xs:x, you've declared that a and [a] are the same type, and the compiler balks. You could perform the append using e.g. xs ++ [x].
Data.Sequence has a type that does support both head and last patterns in the operators :<| and |>:.
In general, (singly linked) lists only make the head element efficiently accessible; operations like appending or even checking lengths are costly. When all you need is a stream or stack, they're great, but a long distance reordering operation like the rotation is better handled by a rope or circular buffer type. Either is available in Haskell, in e.g. container's Seq or ring-buffer's RingBuffer. Data.ByteString.Lazy and Data.Text.Lazy are also rope types.

Haskell map function, return a list without zeroes

Here is my code:
x = map classify[1..20]
classify :: Int -> Int
classify n
| n `mod` 2 == 0 = n + 2
| otherwise = 0
When calling x it returns a list
[0,4,0,6,0,8,0,10,0,12,0,14,0,16,0,18,0,20,0,22]
How can I specify that I want just numbers that are not 0 is list:
[4,6,8,10,12,14,16,18,20,22]
You can use a filter :: (a -> Bool) -> [a] -> [a] for this. This function takes a function (of type a -> Bool called the "predicate") and a list, and it generates a list of values where the predicate is satisfied (returns True for that element).
So you can filter out zeros with:
filter (0 /=) mylist
For your sample list, this generates:
Prelude> filter (0 /=) [0,4,0,6,0,8,0,10,0,12,0,14,0,16,0,18,0,20,0,22]
[4,6,8,10,12,14,16,18,20,22]
That being said, for this specific case, you can save yourself the trouble from generating such elements in the first place by making "hops of 2":
x = map classify [2, 4..20]
This thus will map a list that contains [2,4,6,8,10,12,14,16,18,20], all the elements in between will - given your function - be mapped to zero. By making hops of two, we avoid calculating these values in the first place. But this of course only works for this specific case.

What do you use for base case for Int -> Int -> [Int] in haskell?

Say for example you have
InttoIntList x y
And its Type conversion was
Int -> Int -> [Int]
How would you establish a base case for two inputs to another list type like [Int]
A base case is not determined by the type of the function. Yes frequently the type can give a hint. For example for a list, a base case is typically the empty list [], but not per se.
Furthermore it is a common misconception that functions take two or more parameters. In Haskell, every function takes exactly one parameter. It is however possible that the output is a function that again takes a parameter (which is the case here).
With thes two issues solved, the question arises what the base case for InttoIntList is. Well a base case is a case with no recursion involved. If I understand your function correctly, you want to generate a list of numbers that each time increment from the first Int to the second Int.
So a base case could be the case where the first Int is greater than the second Int. In that case, we probably would want to return an empty list, so:
intToIntList m n | m > n = [] -- base case
and then the recursive case is when m <= n. In that case we typically would want to return a list that starts with m followed by the list that arises from intToIntList (m+1) n, so:
| otherwise = m : intToInt (m+1) n
Here (:) :: a -> [a] -> [a] is a list constructor. It creates a list with m the head (first element) and intToInt (m+1) n the tail (remaining elements).
or putting it together:
intToIntList :: Int -> Int -> [Int]
intToIntList m n | m >= n = []
| otherwise = m : intToIntList (m+1) n

Haskell List of Tuples Compare Pair

I am new to Haskell and I am trying some stuff out. I am having some trouble comparing tuples elements.
Let's say I have a tuple [(1,3),(2,1),(4,4)].
I want to compare each pair index with each other and save some data into a counter value and return that value.
For example what I want is this:
Tuple: [(a,b),(c,d),(e,f)]
When a>b I want to add 3 to the counter.
When a==b I want to add 1 to the counter.
Otherwise add 0 to the counter. Same for (c,d) and (e,f).
After iterating through my tuples I want to return the counter.
So in my example I have tuple [(1,3),(2,1),(4,4)].
The function should do
Since 1<3 add 0 to counter.
Since 2>1 add 3 to counter.
Since 4=4 add 1 to counter.
And after all return 0+3+1 = 4.
Any ideas? Thank you in advance!
(Edit)
calculateWins :: [(Int,Int)]->Int
calculateWins d ((a,b) :xs) = x
where x
|a>b = 3
|a==b = 1
|otherwise = 0
This looks like the point system of a soccer cup (and some other sports). Instead of implementing a function that calculates the sum, we better first aim to calculate something that calculates the score for one such tuple, so something like:
score :: Ord a => (a, a) -> Int
By using a as type, we can use any type of values, as long as we can compare them (the Ord type constraint). So we can write something like:
score (x, y) = -- ...
now in case x > y, then the score is 3 points, in case x == y, then the score is 1 point, and finally in case x < y (otherwise), then the score is 0 points, so we can write it as:
score :: Ord a => (a, a) -> Int
score (x, y) | x > y = 3
| x == y = 1
| otherwise = 0
So now we can perform a map score to calcuate a list of scores, and by using sum, we can calculate the sum of those points, like:
calculateWins :: Ord a => [(a, a)] -> Int
calculateWins = sum . map score
Hint: use a function of type (a -> b) -> [a] -> [b] to transform the list of tuple into a list of your summands (3 or 1 or 0), and use another function of type [a] -> a to get the sum.
The Hoogle is a very nice site for looking up Haskell functions, both by name and by signature.
Please do try these things out before simply asking for the complete code; that helps neither of us.

Haskell parameters - comparison operators

I'd like to define a function whose parameter takes in a list and an operator. This is what I currently have. I'm trying to define a higher order function that can find the minimum or the maximum.
largest :: (a -> a -> Bool) -> a
largest = findType (>)
findType :: (a -> a -> Bool) -> [a] -> a
findType op [] = error "empty list"
findType op [x] = x
findType op (x:xs)
| x op maxTail = x
| otherwise = maxTail
where maxTail = findType op xs
However, it's not currently working.
You can either write a function that accepts any a -> a -> Bool function parameter, or use the fact that comparable data types implement Ord class.
Here is a piece of code showing both methods to check if a list is sorted
option1 :: (a->a->Bool) -> [a] -> Bool
option1 op (a:b:ls) = op a b && option1 op (b:ls)
option1 op _ = True
option2 :: (Ord a) => Ordering -> [a] -> Bool
option2 op (a:b:ls) = compare a b == op && option2 op (b:ls)
option2 op _ = True
main = do
let ls = [1, 2, 3]
print $ option1 (<) ls
print $ option2 LT ls
Note that the 2nd method requires the use of Ordering data type which only has values LT, EQ and GT (meaning <, = and > respectively). You could make it more flexible by passing, say, a list of acceptable Ordering values or some other data structure, however, in most cases 1st option is more appropriate.
Your code as two different problems. Let's address the one generating the compiler error first.
You gave to findType the following signature:
findType :: (a -> a -> Bool) -> [a] -> a
the intent being to extract from the list given as the second parameter the bound as dictated by the ordering predicate provided as the first parameter.
However, in the last line of the very findType function definition, you bind maxTail to the expression findType xs, which omits the predicate.
The correct line is of course:
where maxTail = findType op xs
Your second error is related to the signature of the largest function, but I will let you find out exactly what it is.
GHC doesn't know that you want to use the function op as an operator into your code, you must tell him, but how can you do that ?
Let's consider the elem function, this function take a value and a list and return True or False depending if the value is present into the list or not.
elem :: Eq a => a -> [a] -> Bool
elem 2 [1,2,3] => True
Basically it's see as a function, and if you want to use them as an operator which can be really useful, you must enclose it with `.
2 `elem` [1,2,3] => True
If you add the remarks of didierc on the call of findType into the where clause, you'll have a working code.
Anyway, It's a very bad idea to put a recursive call into a guard, the code is hardest to read, and I'm not sure be it could lead to performance issue. You need to learn how to use an accumulator, take a look on this
Note
Conversely when a function is considered by default as an operator, to use it as a function just enclose it with ().
2 : [] => [2]
(:) 2 [] => [2]

Resources