First off, I would like to make you all aware that I'm very new to Haskell, so to increase knowledge etc, I've been trying out questions and I'm pretty stuck on one. I think I'm nearly there but some more experienced advice would be appreciated. Here's the question:
A sporting team is represented by it's name and the amount of points they scored in their last games like so ("Newcastle",[3,3,3,0]). This data is modelled by the type definitions:
type TName = String
type Points = [Int]
type Team = (TName,Points)
From this I have to define the following function that orders one team higher than another if their points sum is greater:
sortPoints :: [Team] -> [Team]
This is what I've tried:
sortPoints :: [Team] -> [Team]
sortPoints [_,()] -> []
sortPoints [_,(x:xs)] = sum[x|x<-xs]
Once I get to here, I'm not too sure how to go about adding the conditions to check the points sum, any pointers would be greatly appreciated as I'm still coming to terms with a lot of Haskell features.
Note: This post is written in literate Haskell. You can save it as Team.lhs and try it. That being said, it's basically a longer version of Carsten's comment. If you still try to figure things out, use hoogle and look for the functions, although it's fine if you manage things with sortBy solely first.
First of all, we're going to work on lists, so you want to import Data.List.
> module Team where
> import Data.List
It contains a function called sortBy:
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
The first argument of sortBy should be a function that compares two elements of your list and returns
LT if the first is less than the second,
EQ if the both are equal,
GT if the first is greater than the second.
So we need something that that takes two teams and returns their ordering:
> -- Repeating your types for completeness
> type TName = String
> type Points = [Int]
> type Team = (TName, Points)
>
> compareTeams :: Team -> Team -> Ordering
Now, you want to compare teams based on their sum of their points. You don't need their name, so you can capture just the second part of the pair:
> compareTeams (_, s1) (_, s2) =
We need the sum of the points, so we define sum1 and sum2 to be the respective sums of the teams:
> let sum1 = sum s1
> sum2 = sum s2
Now we can compare those sums:
in if sum1 < sum2
then LT
else if sum1 == sum2
then EQ
else GT
However, that's rather verbose, and there's already a function that has type Ord a => a -> a -> Ordering. It's called compare and part of the Prelude:
> in sum1 `compare` sum2
That's a lot more concise. Now we can define sortTeams easily:
> sortTeams :: [Team] -> [Team]
> sortTeams = sortBy compareTeams
And that's it, we're done!
Fine, I lied, we're not 100% done. The module Data.Ord contains a function called comparing that's rather handy:
comparing :: Ord b => (a -> b) -> a -> a -> Ordering
comparing f x y = f x `compare` f y -- or similar
Together with snd and sum you can define sortTeams in a single line:
sortTeams = sortBy (comparing $ sum . snd)
The alternative on mentioned by Carsten is on from Data.Function:
sortTeams = sortBy (compare `on` sum . snd)
Related
I want a function maxfunct, with input f (a function) and input n (int), that computes all outputs of function f with inputs 0 to n, and checks for the max value of the output.
I am quite new to haskell, what I tried is something like that:
maxfunct f n
| n < 0 = 0
| otherwise = maximum [k | k <- [\(f, x)-> f x], x<- [0..n]]
Idea is that I store every output of f in a list, and check for the maximum in this list.
How can I achieve that?
You're close. First, let's note the type of the function we're trying to write. Starting with the type, in addition to helping you get a better feel for the function, also lets the compiler give us better error messages. It looks like you're expecting a function and an integer. The result of the function should be compatible with maximum (i.e. should satisfy Ord) and also needs to have a reasonable "zero" value (so we'll just say it needs Num, for simplicity's sake; in reality, we might consider using Bounded or Monoid or something, depending on your needs, but Num will suffice for now).
So here's what I propose as the type signature.
maxfunct :: (Num a, Ord a) => (Int -> a) -> Int -> a
Technically, we could generalize a bit more and make the Int a type argument as well (requires Num, Enum, and Ord), but that's probably overkill. Now, let's look at your implementation.
maxfunct f n
| n < 0 = 0
| otherwise = maximum [k | k <- [\(f, x)-> f x], x<- [0..n]]
Not bad. The first case is definitely good. But I think you may have gotten a bit confused in the list comprehension syntax. What we want to say is: take every value from 0 to n, apply f to it, and then maximize.
maxfunct :: (Num a, Ord a) => (Int -> a) -> Int -> a
maxfunct f n
| n < 0 = 0
| otherwise = maximum [f x | x <- [0..n]]
and there you have it. For what it's worth, you can also do this with map pretty easily.
maxfunct :: (Num a, Ord a) => (Int -> a) -> Int -> a
maxfunct f n
| n < 0 = 0
| otherwise = maximum $ map f [0..n]
It's just a matter of which you find more easily readable. I'm a map / filter guy myself, but lots of folks prefer list comprehensions, so to each his own.
As the questions states, I am having a little trouble with defining a function with parameters different types. (array of Num, two parameters Int and returning Int).
This is function title:
_sum_divide :: (Num a) => [a] -> (Int b) => b -> b -> b
And I get this error I cannot figure out
`Int' is applied to too many type arguments
In the type signature for `_sum_divide':
_sum_divide :: Num a => [a] -> Int b => b -> b -> b
Sorry for the silly error, I am a noob with Haskell.
Thanks, have a good day/evening.
This seems to be a basic confusion between the concepts of type classes and of types. OO languages throw these all together, but in Haskell they are fundamentally different things.
A type is a set† of values. For example, the type Bool contains the values False and True. The type Int contains the values 0, 1 ... 9223372036854775807 and their negatives.
A type class is a set of types. For example, the class Num contains the type Int, the type Double, the type Rational... and whatever type T of your own, if you just define an instance Num T.
Generally, types are used in function signatures just by naming them. For instance,
foo :: [Int] -> [Int]
foo = map (*3)
is a function accepting a list of Int numbers (i.e. values of type Int), and gives another such list as the result (wherein each entry is tripled).
There is no constraint at all in the signature of foo. I could actually add one, like
foo :: Num Int => [Int] -> [Int]
This would express that the function needs Int to be an instance of the Num class to work. Well, it does need that in order to be able to calculate *3, but the constraint is superfluous, because we know that Int is a Num instance, the compiler doesn't just forget about that.
Where constraints are really useful is in polymorphic functions. For example, the following function triples every entry in a list of numbers, and doesn't care what particular type the numbers have:
foo :: Num n => [n] -> [n]
foo = map (*3)
This notation with type variables like a is actually shorthand for
foo :: ∀ n . Num n => [n] -> [n]
meaning, for all numerical types n, the function foo maps lists of n-values to lists of n-values.
It's important that constraints are completely separate‡ from the actual type specification in a signature. For instance, to specify for a polymorphic function [a] -> b -> b -> b that a should be a Num instance and b an Integral instance (the class of whole-number types, containing amongst other Int), you'd write
sum_divide :: (Num a, Integral b) => [a] -> b -> b -> b
Alternatively, if you really mean Int – that's just a single type, no reason to introduce a type variable for it.
sum_divide :: Num a => [a] -> Int -> Int -> Int
...although, you can still introduce the b variable if you like. You'll need an equational constraint (those are basically ad-hoc type classes containing only a single type)
{-# LANGUAGE TypeFamilies #-}
sum_divide :: (Num a, b ~ Int) => [a] -> b -> b -> b
†Mathematicians would object about several levels of differences between types, sets and classes. Read my notion of “set” as just “collection of things”.
‡In more complicated settings you can actually mix constraints and types, but that's advanced stuff.
The signature for a function that takes list of Nums and 2 int, and returns an int is:
_sum_divide :: (Num a) => [a] -> Int -> Int -> Int
The part before the thick arrow specifies the constraints. The part after it is where you use the constraints.
You had 2 main issues:
There should only 1 list of constraints in a signature.
Int isn't a Typeclass. (Num a) means a can be any type that supports the Num Typeclass. Int however is a concrete type, not a Typeclass, so (Int b) doesn't make sense.
I want to be able to make operators such as found in VB(.net) like shown below
Console.WriteLine ( 16 Mod 2 )
produces an output shown below
0
As you can see, this makes code slightly easier to read. How would I go about making functions that do this?
I have tried the following format
equal :: Integer -> Integer -> bool
x `equal` y = x == y
and I get the following error
*Main> 5 equal 5
<interactive>:1:1: error:
* Non type-variable argument
in the constraint: Num ((Integer -> Integer -> Bool) -> t -> t1)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall t t1.
(Num ((Integer -> Integer -> Bool) -> t -> t1), Num t) =>
t1
*Main>
What is going wrong and how do I do it correctly?
You need to use backticks around equal when you call it, exactly as you did to define it.
5 `equal` 5
The way you wrote it, Haskell thinks you're trying to pass equal as an argument to 5, rather than the other way around.
I'm reviewing an old exam in my Haskell programming course and I can't seem to wrap my head around this function (I think there is just too little information given).
The code given is
myId x = x
function n f
| n > 0 = f . function (n-1) f
| otherwise = myId
I know that if I for example call the function with the input 2 (*2), I will get a function as result. And if I call it with (-2) (*2) 1 I will get the result 1.
I just don't know how? Also I can't wrap my head around the typecast of the function.
I know that these two options are correct but I don't understand why (probably parentheses that confuse me at the moment).
function :: (Num a, Ord a) => a -> (a -> a) -> a -> a
function :: (Num a, Ord b) => a -> (b -> b) -> b -> b
Anyone that can clarify how I should "read" this function and how I should understand how the typecast works (been reading my Programming in Haskell literature and from Learn You a Haskell but been going in circle for a few days now).
function takes some number n and a function f :: a -> a, and composes that function with itself n times, returning another function of type a -> a. When the returned function is applied to a value of type a, the result is essentially the same as executing f in a loop n times, using the output of each previous step as the input for the next.
Perhaps it is easier to see the similarity if the final parameter is made explicit:
function :: (Ord a, Num a) -> a -> (b -> b) -> b -> b
function n f x
| n > 0 = f (function (n-1) f x)
| otherwise = x
This is functionally equivalent to your point-free function.
In Haskell, a function f :: a -> b -> c can be interpreted either as "a function that takes an a and a b and returns a c" or "a function that takes an a and returns a function from b to c". When you apply a function to one or more inputs, think of each input as eliminating one of the function's arguments. In this instance, function 10 returns a new function with type (a -> a) -> a -> a, and function 2 (*2) returns a function with type Num a => a -> a.
When you think of it this way, it should hopefully be clear why function (-2) (*2) 1 returns a number while function 2 (*2) returns a function. There is no type casting going on; when you are applying the three argument function to two inputs, you get another function back instead of a value, since you didn't provide the final input needed to compute that value.
Say we have a list of coordinates like:
(1,2)
(0,3)
(4,1)
(0,3)
(-2,3)
(6,5)
And we wanted to result in the following list, which is defined as the summation of each consecutive coordinates. (Sorry bad definition) like so:
(1,5)
(4,4)
(4,4)
(-2,6)
(4,8)
So there exists a set A = (a,b,c,...,n) where a,b,c,...,n are coordinates in R^2.
There exists a function f such that f(A) = B = (a+b,b+c,c+d,...,n-1+n).
~
How would you write something like that in a functional language like Haskell? A program that applies f to a given A to give B.
You can use zip to zip the list with its tail, you get pairs of pairs like [((1,2), (0,3)), ((0,3),(4,1)), ...]. Then you can use map to replace each pair of pairs with its sum. Or you can use zipWith which is basically zip + map in one function, except the function given to zipWith has type a -> b -> c, not (a,b) -> c:
summedCoords = zipWith (\ (a,b) (c,d) -> (a+c, b+d)) coords (tail coords)
You can write a generic function like this
g:: (a -> a -> b) -> [a] -> [b]
g f (x1:x2:xs) = (f x1 x2):(g (x2:xs))
g _ (x1:[]) = []
and pass it your add function
f = g f' where
f' (a,b) (a',b') = (a+a', b+b')