Haskell: Exercise problem (Convert Currencies that consist of two seperate Integers) - haskell

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...

Related

The javascript thing is weird. I don't know if that happens

i found strange result of javascript
javascript
var a=123e65;
console.log(a);
javascript
result:1.23e+67 ;
why..this..?
I started studying JavaScript. During the study, I found strange results during various attempts. I can't figure out how to get that result...
Well, the result is correct. Its math: in your variable a, the value is 123e65 (that e before the 65 means "raised to the base 10". So the value 123e65 = 123x10^65).
In scientific notation, only numbers between 1 and 10 are valid. Ex: 1500 -> 1.5e3 or 1.5x10^3
in the value of your variable a, you are exponentiating a number greater than 10, (in this case, 123 exponentiated to 65). So javascript just adjusts that number, that is, it leaves 123 as a number between 1 and 10 (returning two places to the left 123 -> 1.23).
To compensate for this two-place return ( 123 -> 1.23) he adds two more numbers in exponentiation (65 -> 67).
So what used to be 123e65 or 123x10^65 became 1.23e67 or 1.23x10^67
This is because the value of variable is being converted to scientific format. Here, e represents '10 to the power'.
Hence, the output is coming as 1.23*10^67

How do I define a data type consisting of other data types?

I want to define the data type Currency, which consists of three other data types. I have the problem that Haskell doesn't recognize the data types as a part of currency, which breaks everything.
My idea was to define the different currencies as their own data types and then add them to the Currency type, which I tried with:
data Euro = MkEuro Integer Integer
data Dollar = MkDollar Integer Integer
data Yen = MkYen Integer
data Currency = Euro | Dollar | Yen
If I want to use the type Currency in any function I get a variation of the following error message:
Couldn't match expected type `Currency' with actual type `Dollar'
Sadly I have to use the type Currency and can't create different functions for all three currencies.
Currently your Currency is constructed as three values, that take no parameters. So Euro is a value, Dollar is a value, and Yen is a value, but not MkYen 15.
You can add parameters to your data constructors like:
data Currency = Euro Euro | Dollar Dollar | Yen Yen
Then you thus can construct a Currency with:
Euro (MkEuro 14 25) :: Currency
The :: Currency is not necessary. The MkEuro will thus construct an object of the Euro type, and then we use the Euro data constructor with type Euro -> Currency to construct a Currency.
Sadly I have to use the type Currency and can't create different functions for all three currencies.
You might want to make a Currency typeclass however, that provides an interface that says what functions a currency should implement, and then make Euro, Dollar, and Yen instances of that typeclass.
The issue with what you attempted is that the Euro, Dollar and Yen defined on the first 3 lines (on the left-hand-side of the = signs) are types, whereas those in the last line, on the right-hand-side, are data constructors. These are different things, which is why you're allowed to give them the same names - but also means that the value Dollar has the type Currency, not the type Dollar.
You had the right idea to create a union type combining the other three - but you are confusing the data constructors (which are just "tags") with the types of the values they hold. You can fix it like this:
data Currency = Euro Euro | Dollar Dollar | Yen Yen
That might look confusing to have the same name twice (three times, too) - but the two occurrences of the name have different meanings. In Euro Euro, for example, the first Euro is a data constructor (a function which "tags" the value), while the second is the type on which the constructor function operates.

Haskell Test Practice Stuck on Tables and Mapping Functions

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?

Substring a text using MOVEL function in RPG

Question:
Is it save to get substring n characters from a text in RPG using MOVEL function which take a text with length x and store it to a variable with capacity n?
Or the only save way to get the first n character is using SUBST?
The background of the question is one of my colleague getting the first 3 characters from a database with 30 char in length is using MOVEL to a variable with length only 3 char (like truncating the rest of it). The strange way, sometimes the receive variable is showing minus character ('-'), sometimes doesn't. So I assume using MOVEL is not a safe way. I am thinking like string in C which always terminated by '\0', you need to use strcpy function to get the copy save, not assigning using = operator.
Anybody who knows RPG familiar with this issue?
MOVEL should work. RPG allows several character data types. Generally speaking, someone using MOVEL will not be dealing with null terminated strings because MOVEL is an old technique and null terminated strings are a newer data type. You can read up on the MOVEx operations and the string operations in the RPG manual. To get a better answer, please post your code, including the definitions of the variables involved.
EDIT: Example of how MOVEL handles signs.
dcl-s long char(20) inz('CORPORATION');
dcl-s short char(3) inz('COR');
dcl-s numb packed(3: 0);
// 369
c movel long numb
dsply numb;
// -369
c movel short numb
dsply numb;
*inlr = *on;
With signed numeric fields in RPG the sign is held in the zone of the last byte of the field. So 123 is X'F1F2F3' but -123 is X'F1F2D3'. If you look at those fields as character strings they will have 123 and 12L in them.
In your program you are transferring something like "123 AAAAAL" to a 3 digit numeric field so you get X'F1F2F3' but because the final character is X'D3' that changes the result to have a zone of D i.e. X'F1F2D3'
You anomaly is dependent on what the 30th character contains. If it is } or any capital letter J to R then you get a negative result. [It doesn't matter whether the first 3 characters are numbers or letters because it is only the second half of the byte, the digit, that matters in your example.]
The IBM manuals say:
If factor 2 is character and the result field is numeric, a minus zone is moved into the rightmost position of the result field if the zone from the rightmost position of factor 2 is a hexadecimal D (minus zone). However, if the zone from the rightmost position of factor 2 is not a hexadecimal D, a positive zone is moved into the rightmost position of the result field. Other result field positions contain only numeric characters.
Don

Convert text to numbers while preserving ordering?

I've got a strange requirements, which I can't seem to get my head around. I need to come up with a function that would take a text string and return a number corresponding to that string - in such a way that, when sorted, these numbers would go in the same order as the original strings. For example, if I the function produces this mapping:
"abcd" -> x
"abdef" -> y
"xyz" -> z
then the numbers must be such that x < y < z. The strings can be arbitrary length, but always non-empty and the string comparison should be case-insensitive (i.e. "ABC" and "abc" should result in the same numerical value).
My first though was to map each letter to a corresponding number 1 through 26 and then just get the resulting number, e.g. a = 1, b = 2, c = 3, ..., z = 26, then "abc" would become 1*26^2 + 2*26 + 3, however then I realised that the text string can contain any text in any language (i.e. full unicode), so this isn't going to work. At this point I'm stuck. Any other ideas before I tell the client to sod off?
P.S. This strange requirement is due to a limitation in a proprietary system that can only do sorting by a numeric field. If the sorting is required by any other field type, it must be converted to some numerical representation - and then sorted. Don't ask.
You can make this work if you allow for arbitrary-precision real numbers, though that kinda feels like cheating. Unicode strings are sequences of characters drawn from 1,114,112 options. You can therefore think of them as decimal base-1,114,113 numbers: write 0., then write out your Unicode string, and you have a real number in base-1,114,113 (shift each character's numeric value up by one so that missing characters have the value 0). Comparing two of these numbers in base-1,114,113 compares the numbers lexicographically: if you scan the digits from left-to-right, the first digit that they disagree on tiebreaks between the two. This approach is completely infeasible unless you have an arbitrary-precision real number library.
If you just have IEEE-734 doubles, this approach won't work. One way to see this is that there are at most 264 possible doubles (or 280 of them if you allow for long doubles) because there are only 64 (80) bits in a double, but there are infinitely many different strings. That eliminates the possibility simply because there are too many strings to go around.
Unfortunately, you can't make this work if you have arbitrary-precision integers. The natural ordering on strings has the fun property that you can find pairs of strings that have infinitely many strings lexicographically between them. For example, notice that
a < ab < aab < aaab < aaaab < ... < b
Now imagine that you have a function that maps each string to an integer that obeys the rules you'd like. That would mean that
f(a) < f(ab) < f(aab) < f(aaab) < f(aaaab) < ... < f(b)
But that's not possible in the integers - you can't have two integers f(a) and f(b) with infinitely many integers between them. (The number of integers between f(a) and f(b) is at most f(b) - f(a) - 1).
So it seems like the answer is "this is possible if you have arbitrary-precision real numbers, it's not possible with doubles, and it's not possible with arbitrary-precision integers." I'd basically label that "not going to happen in practice" even though it's theoretically possible. :-)

Resources