This is the question from my exam practice paper:
The following table gives the names, grades and age of people employed by a
company:
Name Grade Age
Able Director 47
Baker Manager 38
Charles Trainee 19
Dunn Director 50
Egglestone Manager 42
i. Define a Haskell type suitable for representing the information in such a
table [10%]
A function avAge is required to find the average age of people in a given grade,
for instance in the example the average age of managers is 40. Give three
alternative Haskell definitions for this function:
ii. using explicit recursion, [20%]
iii. using mapping functions, [20%]
iv. using list comprehensions. [20%]
The table isn't very clear as I couldn't paste the proper table but you can basically see there are 3 columns and multiple rows, one for name, one for grade, one for age. So as you can see the first question "i" is to define a haskell type that is suitable for representing an information in such a table. Keep in my that the real table has lines of course.
So how do I define a function to do this? Does define a function mean e.g. "[String] -> String -> Int" or I have to write up a function that does something?
Finally, about the avAGe to find the average age of people what are the ideas behind doing it with mapping functions? I have planned out for explicit recursion but I'm really struggling to fit mapping functions (map, foldr, filter, etc) to this.
A suitable type would be one where each row has a data type and maybe you can use an existing collection type for holding multiple rows. To start you off:
data Entry = Entry __________ deriving (Eq, Show)
type Entries = __________
So what should go in the blank? It'll need to be able to hold a name, a grade, and an age. For Entries, you should be able to use a built-in type to store all these rows, presumably in order.
Are the grades from a fixed number of valid values? Then you might consider using an ADT to represent them:
data Grade
= Trainee
| Manager
| Director
-- | AnyOtherNameYouNeed
deriving (Eq, Show)
If not, then you can just use Strings, but I would still give them a name:
type Grade = String
So now that you have your types set up, you can work on the implementations of avAge. You need explicit recursion, mapping, and list comprehension. The function needs to take Entries and a Grade and return an average of the ages that match that Grade, so the type signature should probably be
avAgeRec :: Entries -> Grade -> Double
avAgeRec entries grade = __________
avAgeMap :: Entries -> Grade -> Double
avAgeMap entries grade = __________
avAgeComp :: Entries -> Grade -> Double
avAgeComp entries grade = __________
This should help you get started, I just don't want to give you the answers since this is a study problem, and it's always better to come up with the answers yourself =)
So now you have
type Grade = String
type Entry = (String, Grade, Int)
type Entries = [Entry]
And with a little filled in from the comments below:
avAgeRec :: Entries -> Grade -> Double
avAgeRec entries grade = __________
avAgeMap :: Entries -> Grade -> Double
avAgeMap entries grade = <calculate average> $ map <get ages> $ filter <by grade> entries
avAgeComp :: Entries -> Grade -> Double
avAgeComp entries grade = __________
Can you get a few more of the blanks filled in now?
Related
I'm still doing the exercise from the book and the one exercise says that I should create a function: value :: Hand -> Int, which returns the value of the hand.
My code so far looks like this:
data Hand = PairOf Rank | ThreeOf1 Rank | ThreeOf2 Suit
value: Hand -> Int
otherwise = 0
--
I now have another problem, because I don't know how to describe "Nothing".
Nothing is described here as a possible hand combination in which Pair, ThreeOf1 and ThreeOf2 do not occur.
Would otherwise = 0 work or doesn't that make much sense?
Thanks again for the suggestions, I corrected them! Thanks also in advance for explanations and help.
otherwise won't work here. What you want is an irrefutable pattern that will match anything, and further since you don't care what gets matched, you specifically want the pattern _:
value :: Hand -> Int
value (PairOf r1) = 1
value (ThreeOf r1) = 2
value (Flush s1) = 3
value _ = 0
Since you don't care about what kind of pair, etc you get, you can also use _ in the other cases:
value :: Hand -> Int
value (PairOf _) = 1
value (ThreeOf _) = 2
value (Flush _) = 3
value _ = 0
If you wanted to match Nothing (or whatever name you come up with that doesn't conflict with the Maybe constructor) specifically, it's just
value Nothing = 0
One of the problems you might be having is that there is no Nothing.
Here's the full type of Hands for holdem:
data HandRank
= HighCard Rank Rank Rank Rank Rank
| OnePair Rank Rank Rank Rank
| TwoPair Rank Rank Rank
| ThreeOfAKind Rank Rank Rank
| Straight Rank
| Flush Rank Rank Rank Rank Rank
| FullHouse Rank Rank
| FourOfAKind Rank Rank
| StraightFlush Rank
deriving (Eq, Ord, Show, Generic)
The extra ranks in the data type are there to distinguish hands, so a pair of aces with a King & Queen kicker beats a pair of aces with a King & Jack kicker. But otherwise, it's the same as your setup.
Once you have a complete transformation from a set of cards to a hand value, there is no nothing. What you might be thinking of as nothing is the HighHand line in the sum type. If your context is that's it for possible hands, then I would add a NoValue to the Hand sum type, as better than outputting a Maybe Hand.
Using the wild cards otherwise _ or value _ introduces a chance of a bug because you might forget about coding up a full house, say, and your existing function would work. If you forget to code one of the sum types, and you don't have a match-any pattern, the compiler will complain. Providing the compiler with all branches of a sum type is also a hot development area of GHC, and it will be fast.
So I got three datatypes Euro, Dollar and Yen. The datatype Currency is one of those.
data Euro = MkEuro Integer Integer
data Dollar = MkDollar Integer Integer
data Yen = MkYen Integer
data Currency = MkE Euro | MkD Dollar | MkY Yen
Now I wanna convert f.e. Dollar to Euro. Lets say 1 Dollar is 0.90 Euro.
I really dont know how to implement that in Haskell. I need a function toEuro that takes in a Currency and converts it into Euro and gives it out as a Currency aswell. The problem is that f.e. Dollar und Cents are split into two seperate Integers and Iam not allowed to use any split or connection functions (if there even is some of these). I have no idea how to calculate with two seperate Integers. Lets say I have 12,20 Dollars and I want it as 10,98 Euros. How do I get it into Euros if 1 Dollar was 0.90 Cent. So I need 12 20 to be 10 98. I just dont see it.
Iam not allowed to use any split or connection functions (if there even is some of these).
It's not clear what you mean by that. I strongly suspect that you're supposed to use pattern matching. Joseph's comment is fine, and possibly helpful, but it sounds like the thing you're missing is how to get the integers you need out of the Currency. Try completing this fragment:
toEuro :: Currency -> Currency
toEuro (MkE e) = MkE e
toEuro (MkD (MkDollar d c)) = let usCents = (100 * d) + c
in MkE (MkEuro ... ...)
...
Protips:
That last ellipsis isn't a mistake, there's a whole line missing.
The first pattern seems awkward; we didn't unpack e into MkEuro eE eC, so why did we have to unpack (MkE e)? The answer is because we had to check that it was actually a Euro; obviously we couldn't just write toEuro e = e. But a "better" compromise may have been to use an "as" pattern: toEuro e#(MkE _) = e.
You suggested using 0.9 as a conversion factor; it seems inevitable that you'll want that to be an argument to your function. It should be your first argument; in Haskell your "subject" argument, the most "data-like" argument, should always go last. (Configuration arguments come first.) But it's more complicated than that because you also have to worry about Yen. I don't know how you're going to want to handle that...
I have a very detailed excel model to calculate the profitability of a project, that we can call P.
The model has been simplified to compute from 3 unrelated variables. I would like to automatically create a table that shows how inputs A, B and C might vary in order to produce a pre-defined level of profitability, P. For instance, if A = 4 & B = 30, then C must = 2 in order for P to equal 20%. Likewise, if A = 5 & B = 25, then C must = 3 in order for P to equal 20%. A and B should be tested at sensible increments, perhaps 8 intervals each.
A laborious (not scalable) equivalent would be to manually define A and B, then goal-seek C to our pre-defined level of P - we'd then repeat for each combination of A and B at the given intervals and record in a two-way table.
I believe a conventional two-way data table would be pratical if the model sitting behind the inputs were greatly simplified, unfortunately this isn't possible.
Thanks to anyone that can lend a hand. Kind regards.
I think the best way to approach this will be with a VBA macro and the prebuilt GoalSeek Function something like this (p is in cell D1) :
Range(”D1”).GoalSeek Goal:=20 _
ChangingCell:=Range(“C1”)
I'm playing Tic Tac Toe and the columns are represented by lists,
so classic 3x3 Tic Tac full of alternating X and O, from bottom to up, for three columns, would be [X,O,X][X,O,X][X,O,X]. Empty would be represented by Empty I guess (is that a good idea or bad idea)
How would I check if a selected column X, is full?
I want to have a function called Checker :: board -> Int -> Bool
Not really sure where to begin on defining the function Checker.
Edit: Clarifications
1) The board (like any real life game of Tic Tac Toe) will start off obviously as
[empty,empty,empty][empty,empty,empty][empty,empty,empty]
or it will start off as the empty list and a function needs to transform it to
[empty,empty,empty][empty,empty,empty][empty,empty,empty]
2) I want to check if the column is full, so to error check. I do not want players to add X's or O's to full columns. Columns could be filled up with any combination of X's and O's, just like mid way in a real life game of Tic-Tac-Toe.
3) The board is a list of lists. Columns by human interpretation are merely lists
So in a tic tac toe board that is ALL X's EXCEPT the middle being an O, is
[X,X,X][X.O,X][X,X,X]
You can check if a given (1-dimensional) list is all X with
all (== X) list
(As long as your data type has an Eq instance, which you can give it with e.g.
data Square = X | O | Empty
deriving (Eq)
).
Similarly, you can check if every element is non-empty with
all (/= Empty) list
or by defining your own function isFull :: Square -> Bool and using all isFull list.
You can extract a column from a list by mapping a list index operator over it.
column n xss = map (!! n) xss
Another way, which is arguably more elegant, is to transpose it and then look at the rows.
I have a following quest:
I have to write program in Haskell which will allow me to create something like excel sheet.
There are columns and rows, and each cell can hold number or string or some function (sum, mean, multiply etc). Each of the functions take as parameters a list of cells which are summed etc.
Now I am trying to figure out how to store this data into my program...
I was thinking about something like this:
data CellPos = CellPos Int Int -- row and col of Cell
data DataType = Text | String | SumFunction | ...... deriving (Enum)
data Cell = Cell CellPos DataType -- but here is a problem , how to put here data with type which depends on DataType???
I wanted just to have big list of Cell and search in it for specified column/row etc
But there must be some better solution for this – maybe some two dimensional array which auto adjust its size or something?
I will have to save/load a sheet to /from file...
Let's answer one question at a time:
data Cell = Cell CellPos DataType
"but here is a problem , how to put here data with type which depends on DataType???"
Put that data into DataType:
data DataType = Text String | Number Double | Function CellPos (DataType -> DataType)
"I wanted just to have big list of Cell and search in it for specified column/row etc. But there must be some better solution for this - maybe some two dimmensional array which auto adjust its size or something?"
I suggest a Map CellPos DataType.
"I will have to save/load a sheet to /from file..."
The simplest thing will probably be to derive Show and Read and use the resulting functions together with readFile and writeFile. The only caveat here (with respect to DataType as defined earlier in this answer) is that functions cannot be serialized. To get around this, make a more explicit type for the functions in cells -- perhaps an abstract syntax tree for some simple expression language.